Sostituisci stringa multilinea nei file


17

Ho un numero di file che voglio aggiornare sostituendo una stringa multilinea con un'altra stringa multilinea. Qualcosa sulla falsariga di:

* Some text, 
* something else
* another thing

E voglio sostituirlo con:

* This is completely
* different text

Il risultato sarebbe che dopo la sostituzione il file contenente il primo blocco di testo conterrà ora la seconda stringa (il resto del file rimane invariato).

Parte del problema è che devo trovare l'elenco dei file da aggiornare nel file system. Immagino di poter usare grep per questo (anche se di nuovo non è così facile da fare con le stringhe multilinea), quindi reindirizzarlo in sed forse?

C'è un modo semplice per farlo? Sed è un'opzione ma è imbarazzante perché devo aggiungere \ n ecc. C'è un modo per dire "prendi l'input da questo file, abbinalo in quei file, quindi sostituiscilo con il contenuto di questo altro file"? Posso usare Python se necessario, ma voglio qualcosa di veloce e semplice, quindi se c'è un'utilità disponibile, preferirei usarlo piuttosto che scrivere il mio script (che so come fare).


Probabilmente dovresti usare perl per questo. stackoverflow.com/questions/1030787/…
orion,

3
Quindi vuoi abbinare some text, something else another thingse si estende o meno su più righe? O vuoi solo abbinare some text,\nsomething else\nanotherthing?
Mikeserv,

2
Modifica la tua domanda e chiarisci qual è esattamente il contenuto di ciascun file e qual è l'output desiderato.
Jimmij,

La stringa si estende su più righe. Ignoro piuttosto lo spazio bianco quando si abbina / sostituisce perché potrebbe non essere assolutamente lo stesso, ma non è un grosso problema se faccio solo 1-1 (nuove righe e tutto).
Ventsyv,

Risposte:


12

Sostituisci "Some ... \ n ... Thing" con il contenuto del file "new" in uno o più file di input

perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt ...
  1. -i per modificare direttamente input.txt
  2. -p0 bere file di input in input e stamparlo alla fine
  3. s/regexp/.../s in regexp .è.|\n
  4. s/.../exp/e sostituito da eval(exp)
  5. nuovo - un file contenente il testo sostitutivo (Questo è completamente ... testo diverso)
  6. se utile puoi espandere il testo originale s/Some text\n...\n...thing\n/...

Come posso fare lo stesso con un file chiamato dire "prima" per cercare il contenuto (multilinea) di quel file? Ho provato ma non funziona.
Kvothe,

@Kvothe, abbiamo bisogno di maggiori dettagli ... Supponendo che "prima" non abbia caratteri speciali, puoi provareperl -i -p0e ' $b= `cat before`; s/$b/Some thing\n/se' input.txt ...
JJoao

E supponendo che "prima" contenga tutti i caratteri speciali (nuove righe, barre, parentesi) tranne 'e `.
Kvothe

5
sed -e :n -e '$!N;/\n.*\n/!{$!bn
};  s/some text,\n* *something else\n* *another thing/this is completely\
different text/;P;D' <infile

Temo che avrai difficoltà a trovare una soluzione adatta a te fino a quando non fornirai una descrizione concreta del problema, ma è per questo che il QA è più adatto, a mio modo di vedere. Forse questo ti darà un'idea - manterrà sempre 3 linee nello spazio del modello alla volta - con un lookahead a 2 linee - mentre scorri in avanti attraverso il file di input solo una linea alla volta.

Dovrebbe essere in grado di far corrispondere la stringa sia che si estenda su più righe o meno - fino a tre, cioè. Ma non ci sono disposizioni per rispecchiare quella disposizione nella sostituzione - si estende sempre su due righe come scritto.


0

Non troppo forte (perché non chech seconda stringa ma è facile da sistemare) e può essere non è posix compilant ma molto semplice:

sed '/^Some text/{:1;/another thing$/!{N;b 1}
     s/.*/this is completely\ndifferent text/g}' input.txt

Il primo comando aggiunge righe da Alcuni testi fino a quando non hanno incontrato un'altra cosa, quindi la seconda riga lo cambia in altri testi.

NOTA La limitazione è che alcuni testi dovrebbero sempre essere seguiti da un'altra cosa .


Il problema è che la stringa potrebbe essere più di 2 righe (fino a una dozzina o giù di lì) e potrebbe contenere altre cose che potrebbero aver bisogno di essere
salvate

@ventsyv Non ci sono problemi con il numero di righe o di separatori: lo script controlla solo l'inizio e la fine. È sufficiente che SE la stringa iniziale sia eccezionalmente in grado di contrassegnare il testo da modificare . Se non è meglio mostrare l'esempio di input per produrre un modello corretto.
Costas,
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.