Sed: Sostituisci lo schema su ogni seconda riga?


10

C'è un modo per dire seddi sostituire il modello ad ogni seconda occorrenza? O almeno su ogni seconda riga? (Certo è possibile con una sceneggiatura, ma mi chiedevo se sedposso farlo).

modificare

ho trovato

sed -e "s/pattern/replacement/g;n"

Ma ha sostituito ogni prima occorrenza, non la seconda.

Esempio

File di input:

I have a pattern in each line
Also the second line has the pattern
Another pattern here
And -- you guess it -- a pattern

Uscita desiderata:

I have a pattern in each line
Also the second line has the replacement
Another pattern here
And -- you guess it -- a replacement

Risposte:


6

vedi /programming/5858200/sed-replace-every-nth-occurrence

La soluzione utilizza awk anziché sed, ma "usa lo strumento giusto per il lavoro". Potrebbe essere o meno possibile farlo in sed ma, anche se lo è, sarà molto più semplice in uno strumento come awk o perl.


1
Usando quello che ho imparato lì ho fatto la cameriera sed -e 'n;s/2004-2009/6e législature/g'che ha risolto il mio problema.
Matthieu Riegler,

1
che non otterrà ogni seconda occorrenza , cercherà il tuo modello su ogni seconda riga . cioè saltare la 1a, 3a, 5a, 7a, ecc. riga. ovviamente, potrebbe funzionare ancora per il tuo documento specifico.
CAS

Sì, lo so. questo è quello di cui avevo bisogno in realtà.
Matthieu Riegler,

14
sed 's/pattern/replacement/2'

Sostituirà la seconda occorrenza su ogni riga che ha il modello.


se hai GNU sed:

sed '1~2N ; s/pattern/replacement/2'

A partire dalla prima riga 1, la riga successiva verrà aggiunta allo spazio del pattern, Nquindi il scomando sostituirà la seconda occorrenza del pattern. quindi sedsposta due righe verso il basso ~2e si ripete.


Non voglio il secondo ma ogni secondo.
Matthieu Riegler,

Ho un modello per riga. Non funzionerà
Matthieu Riegler,

sarebbe stato bello saperlo prima. Quindi lo schema si verifica sulla riga uno, due, tre e quattro (ecc.) E si desidera sostituire lo schema sulla riga due, quattro, ecc.?
llua

un'alternativa più breve potrebbe essere code(sed '1 ~ 2s / modello / sostituzione /')
jaap

2

La semplice interpretazione:

Sulla prima riga che contiene almeno un'occorrenza di PATTERN si desidera ignorarlo e stampare la riga così com'è. Nella seconda riga che contiene almeno un'occorrenza di PATTERN si desidera sostituire la prima istanza di PATTERN con SOSTITUZIONE. Sulla terza riga che contiene almeno un'occorrenza di PATTERN si desidera stampare la riga così com'è. Nella quarta riga che contiene almeno un'occorrenza di PATTERN si desidera sostituire la prima istanza di PATTERN con SOSTITUZIONE. E così via. Le righe che non corrispondono a PATTERN devono essere stampate senza modifiche.

Questo può essere fatto facilmente con Sed in questo modo:

sed -e '/PATTERN/ { :inside' -e 'n;s//REPLACEMENT/;t' -e 'b inside' -e '}'

Oppure, con meno spazi bianchi e un'etichetta più corta:

sed -e '/PATTERN/{:i' -e 'n;s//REPLACEMENT/;t' -e 'b i' -e '}'

EDIT: ho appena riletto la domanda e individuato l'interpretazione più dura:

Sostituisci la seconda occorrenza di PATTERN nell'intero documento con SOSTITUZIONE, indipendentemente dal fatto che si verifichi sulla stessa riga della prima occorrenza o meno. Lascia inalterate la prima e la terza occorrenza. Eccetera.

Credo che ciò possa essere fatto anche con Sed, anche se è MOLTO più complicato e credo che dipenda dall'espressione regolare da usare. Cercherò di elaborare qualcosa e pubblicarlo, ma lascerò questa risposta in piedi con la versione semplice sopra per ora.


sostituisci test con un quit e prendi input come, { sed '...'; cat; } <inputper un solo rimpiazzo
mikeserv

1

Eri molto vicino, salta solo la prima riga:

sed '1n;s/pattern/replacement/;n'

Perché dovrebbe awkessere lo strumento migliore in questo caso?


0

Un modello di simbolo all'interno di una riga: sed 's / (a ​​[^ a] *) a / \ 1c / g'

Ogni secondo motivo (può apparire solo una corrispondenza di motivo per riga. Se vengono visualizzate due o più corrispondenze per una riga, verrà sostituita solo la seconda)

echo -e "test\nreplace_me\ntest\ntest\nreplace_me\nreplace_me\nreplace_me" | \
sed '/replace_me/{:a;N;/replace_me.*replace_me/!Ta;s/replace_me/replaced/2;}'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.