2009-05-18 8 views

Répondre

12

L'astuce consiste à stocker la dernière ligne vue dans "l'espace de maintien".

sed -n ' 
/^xxxx/{n 
     n 
     x 
     d 
     } 
x 
1d 
p 
${x 
    p 
} 
' <input file> 

À partir de la x - échanger la ligne d'entrée en cours avec l'espace de maintien (x), puis pour la première ligne ne pas imprimer quoi que ce soit (1d), les lignes suivantes impriment la ligne juste permuté de l'espace d'attente (p), sur la dernière ligne permutez à nouveau l'espace de conservation et imprimez ce qu'il contenait ($x{x p}) Cela laisse ce qu'il faut faire lorsque nous touchons la ligne cible (commençant /^xxxx/) - lire les deux lignes suivantes dans l'espace modèle (n n) et échangez l'espace de motif avec l'espace de maintien (x) - cela laisse l'espace de maintien avec la ligne suivante que nous voulons imprimer et l'espace de motif avec la ligne avant le match, qui h nous ne voulons pas, donc nous Ditch il (d)

+0

Une autre explication de la Commande 'x' qui "change" l'espace du motif avec le tampon de maintien: http://www.grymoire.com/Unix/Sed.html#uh-53 –

+0

Je ne peux pas exécuter le script ci-dessus. il dit sed: FONCTION/^ motif/{n n x d} x 1d p $ {x p} ne peut pas être analysé pas sûr pourquoi? –

0

Voilà comment je le ferais en perl peut-être que ça peut vous aider à vous mettre sur la bonne voie ... Bonne chance!

open(INFILE,"<in.txt"); 
my(@arrayOutBoundData, $skipNextLine)l 
for (<INFILE>) { 
    if (not $skipNextLine) { 
     if (/^xxxx$/) { 
      pop(@arrayOutBoundData); 
      $skipNextLine = 1; 
     } else { 
      push(@arrayOutBoundData,$_); 
     } 
    } 
$skipNextLine = 0 
} 

open(OUTFILE,">out.txt"); 
for (@arrayOutBoundData) { 
    print OUTFILE; 
} 

(Non testé pas perl sur ce système s'il vous plaît pardonnez-tout sur le site.)

1

Vous pouvez consulter this document. Il couvre l'utilisation sed pour travailler avec plusieurs lignes.

-1
grep -v -f <(grep -1 "xxxx" file) file 
0

Cela pourrait fonctionner pour vous (GNU sed):

echo -e "a\nyyyy\nxxxx\nzzzz\nb" | sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' 
a 
b 

Cela permet de maintenir une fenêtre de deux lignes dans l'espace de travail et Si l'expression rationnelle requise est trouvée dans la première ou la deuxième ligne, lit la ligne suivante, puis supprime toutes les trois lignes. Les cas de bord sont si l'expression rationnelle est trouvée dans la première ou la dernière ligne lorsqu'il n'y a pas de ligne avant/après. Dans ces cas, seules deux lignes peuvent être supprimées. Par ailleurs, cette solution a peut-être mis au jour un bug possible dans GNU sed. Le drapeau M d'une adresse permet aux métacaractères ^ et $ d'être utilisés comme marqueurs de longueur zéro dans une expression rationnelle pour le début et la fin de ligne dans les chaînes multilignes. L'adresse vide // réutilise une adresse précédemment indiquée. Cette adresse devrait-elle comporter un drapeau multiligne? À l'heure actuelle, il semble inclure le drapeau même si on ne dit pas à savoir

sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' file 

produit un autre (correct) résultat à:

sed 'N;/^xxxx/M{//d;$!N;d};P;D' file 

si xxxx apparaît sur la deuxième ligne d'un fichier.

+0

Presque, mais il veut aussi que Zzzz disparaisse. –

+0

@SamuelEdwinWard simple correctif voir modification. – potong

0

Vous pouvez utiliser les éléments suivants:

sed -n '/xxxx/{N;s/.*//;x;d;};x;p;${x;p;}' 

Cela remplacera 3 lignes avec une ligne vide.

0

Vous pouvez d'abord inverser le fichier, utilisez sed pour supprimer la ligne associée et la ligne suivante (ou lignes, +Nd en commande sed), et enfin inverser le résultat en arrière:

tac old.file | sed -e '/xxxx/,+1d' | tac > new.file 
Questions connexes