Sto cercando di capire come replicare un singolo intervallo di righe in un file di testo. L'intervallo inizia con una riga che è univoca nel file, ma termina con una riga che può esistere in più punti del file.
Ecco alcuni esempi di input che devo elaborare:
I have no imagination so this sample text will Common be boring. But it does demonstrate the problem I am trying to solve. Common Hi mom! This is a unique line. And here is some more text that should be copied as well. Common Followed by text that should not be copied.
Le righe che devo duplicare e modificare sono in grassetto per indicarle qui.
L'output di cui ho bisogno è:
I have no imagination so this sample text will Common be boring. But it does demonstrate the problem I am trying to solve. Common Hi mom! This is a changed line. And here is different more text that should be copied as well. Common This is a unique line. And here is some more text that should be copied as well. Common Followed by text that should not be copied.
L'output aggiuntivo è in grassetto per renderlo più chiaro.
Ho bisogno di ottenere l'intervallo di righe che iniziano con la riga:
This is a unique line
e termina con la riga:
Common
Tale intervallo di righe deve essere inserito prima appena prima dell'intervallo di righe originale. La copia dell'intervallo di righe corrispondente dovrà essere leggermente modificata.
La riga "Comune" che termina l'intervallo può essere essa stessa presente in molti punti all'interno del file.
Mi è venuto in mente un awk
funzionante script ma sembra molto più complicato di quanto dovrebbe essere. Il mio awk
le competenze sono inesistenti.
/This is a unique line/{flag=1}
/Common/{
if (flag > 0) {
n=m;
sub("some","different",n);
sub("unique","changed",n);
print n "\n" $0 "\n" m;
m=""
};
flag=0
};
flag{
if (length(m) > 0) {
m=m "\n" $0
} else {
m=$0
}
}
!flag{ print }
C'è un modo più pulito e meno dettagliato per implementarlo? Sono aperto ad altre opzioni oltre a awk
. Deve solo essere un comando standard disponibile su macOS.
Risposta accettata:
awk '/This is a unique line/,/Common/{
H = H RS $0
if ( $0 ~ /Common/ ) {
g = H
sub("\n","",g)
sub("some","different",g)
sub("unique","changed",g)
$0 = g H
} else { next }
}1' inputfile
Ecco il sed
codice (che ho mostrato nella sezione Risposte) tradotto in awk
.
Nota che il codice che stai avendo ti stai assumendo la responsabilità di attivare/disattivare il awk
flag variabile per tenere traccia delle linee. Ma mentre, awk
lo fa già per te sotto il cofano la stessa identica cosa quando usi il suo range
operatore ,