GNU/Linux >> Linux Esercitazione >  >> Linux

Duplicato, con poche piccole modifiche, poche righe in un file di testo?

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 ,


Linux
  1. Cat Line X to Line Y su un file enorme?

  2. Come rimuovere le righe duplicate all'interno di un file di testo?

  3. Inserire nuove righe con valori mancanti (na)?

  4. Rimuovere in modo efficiente le prime due righe da un file di testo?

  5. Elimina le righe consecutive in Csv con valori duplicati in un campo, ma mantieni l'ultima riga?

Comando Diff in Linux con esempi

Manipolazione del testo dalla riga di comando con grep

Come trovare le righe più lunghe in un file in Linux

Come contare le righe in un file in UNIX/Linux

Come sostituire il testo come sed con python?

Trova e sostituisci il testo in un file tra un intervallo di righe usando sed