Quando lavori con file di testo, dovrai spesso trovare e sostituire stringhe di testo in uno o più file.
sed
è una s tream ndr itor. Può eseguire la manipolazione del testo di base su file e flussi di input come pipeline. Con sed
, puoi cercare, trovare e sostituire, inserire ed eliminare parole e righe. Supporta espressioni regolari di base ed estese che ti consentono di abbinare modelli complessi.
In questo articolo parleremo di come trovare e sostituire le stringhe con sed
. Ti mostreremo anche come eseguire una ricerca ricorsiva e sostituire.
Trova e sostituisci String con sed
#
Esistono diverse versioni di sed
, con alcune differenze funzionali tra loro. macOS utilizza la versione BSD, mentre la maggior parte delle distribuzioni Linux viene fornita con GNU sed
preinstallato per impostazione predefinita. Useremo la versione GNU.
La forma generale di ricerca e sostituzione del testo utilizzando sed
assume la seguente forma:
sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE
-i
- Per impostazione predefinita,sed
scrive il suo output nello standard output. Questa opzione dice ased
per modificare i file sul posto. Se viene fornita un'estensione (ex -i.bak), viene creato un backup del file originale.s
- Il comando sostitutivo, probabilmente il comando più usato in sed./ / /
- Carattere delimitatore. Può essere qualsiasi carattere tranne solitamente la barra (/
) viene utilizzato il carattere.SEARCH_REGEX
- Stringa normale o un'espressione regolare da cercare.REPLACEMENT
- La stringa di sostituzione.g
- Bandiera di sostituzione globale. Per impostazione predefinita,sed
legge il file riga per riga e cambia solo la prima occorrenza delSEARCH_REGEX
su una linea. Quando viene fornito il flag di sostituzione, tutte le occorrenze vengono sostituite.INPUTFILE
- Il nome del file su cui vuoi eseguire il comando.
È buona norma mettere virgolette intorno all'argomento in modo che i metacaratteri della shell non si espandano.
Vediamo come possiamo usare il sed
comando per cercare e sostituire il testo nei file con alcune delle opzioni e dei flag più comunemente usati.
A scopo dimostrativo, utilizzeremo il seguente file:
file.txt123 Foo foo foo
foo /bin/bash Ubuntu foobar 456
Se il g
flag viene omesso, viene sostituita solo la prima istanza della stringa di ricerca in ogni riga:
sed -i 's/foo/linux/' file.txt
123 Foo linux foo
linux /bin/bash Ubuntu foobar 456
Con il flag di sostituzione globale sed
sostituisce tutte le occorrenze del modello di ricerca:
sed -i 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456
Come avrai notato, la sottostringa foo
all'interno del foobar
la stringa viene sostituita anche nell'esempio precedente. Se questo non è il comportamento desiderato, utilizzare l'espressione di confine di parola (\b
) a entrambe le estremità della stringa di ricerca. Ciò garantisce che le parole parziali non corrispondano.
sed -i 's/\bfoo\b/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456
Per fare in modo che il pattern non faccia distinzione tra maiuscole e minuscole, usa I
bandiera. Nell'esempio seguente stiamo usando sia il g
e I
bandiere:
sed -i 's/foo/linux/gI' file.txt
123 linux linux linux
linux /bin/bash Ubuntu linuxbar 456
Se vuoi trovare e sostituire una stringa che contiene il carattere delimitatore (/
) dovrai utilizzare la barra rovesciata (\
) per sfuggire alla barra. Ad esempio per sostituire /bin/bash
con /usr/bin/zsh
useresti
sed -i 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt
L'opzione più semplice e molto più leggibile consiste nell'utilizzare un altro carattere delimitatore. La maggior parte delle persone usa la barra verticale (|
) o due punti (:
) ma puoi usare qualsiasi altro carattere:
sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt
123 Foo foo foo
foo /usr/bin/zsh Ubuntu foobar 456
Puoi anche usare le espressioni regolari. Ad esempio, per cercare tutti i numeri a 3 cifre e sostituirli con la stringa number
useresti:
sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt
number Foo foo foo
foo /bin/bash demo foobar number
Un'altra caratteristica utile di sed è che puoi usare il carattere e commerciale &
che corrisponde al modello abbinato. Il personaggio può essere utilizzato più volte.
Ad esempio, se vuoi aggiungere parentesi graffe {}
intorno a ogni numero di 3 cifre, digitare:
sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt
{123} Foo foo foo
foo /bin/bash demo foobar {456}
Ultimo ma non meno importante, è sempre una buona idea fare un backup quando si modifica un file con sed
. Per farlo, fornisci un'estensione per il file di backup a -i
opzione. Ad esempio, per modificare il file.txt
e salva il file originale come file.txt.bak
useresti:
sed -i.bak 's/foo/linux/g' file.txt
Per assicurarti che il backup sia stato creato, elenca i file con ls
comando:
ls
file.txt file.txt.bak
Trova e sostituisci ricorsivo #
A volte potresti voler cercare ricorsivamente nelle directory i file che contengono una stringa e sostituire la stringa in tutti i file. Questo può essere fatto usando comandi come find
o grep
per trovare ricorsivamente i file nella directory e reindirizzare i nomi dei file a sed
.
Il comando seguente cercherà ricorsivamente i file nella directory di lavoro corrente e passerà i nomi dei file a sed
.
find . -type f -exec sed -i 's/foo/bar/g' {} +
Per evitare problemi con i file che contengono spazio nei loro nomi, usa il -print0
opzione, che dice a find
per stampare il nome del file, seguito da un carattere null e reindirizzare l'output a sed
usando xargs -0
:
find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'
Per escludere una directory, usa il -not -path
opzione. Ad esempio, se stai sostituendo una stringa nel tuo repository git locale per escludere tutti i file che iniziano con punto (.
), usa:
find . -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'
Se vuoi cercare e sostituire il testo solo su file con un'estensione specifica, utilizzerai:
find . -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'
Un'altra opzione è usare grep
comando per trovare ricorsivamente tutti i file contenenti il modello di ricerca e quindi reindirizzare i nomi dei file a sed
:
grep -rlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'
Conclusione #
Sebbene possa sembrare complicato e complesso, all'inizio cercare e sostituire il testo nei file con sed
è molto semplice.
Per ulteriori informazioni su sed
comandi, opzioni e flag, visita il manuale di GNU sed e il tutorial di Grymoire sed.
Se hai domande o feedback, sentiti libero di lasciare un commento.