Introduzione
Il comando sed
, abbreviazione di stream editor, esegue operazioni di modifica sul testo proveniente dallo standard input o da un file. sed
modifica riga per riga e in modo non interattivo.
Ciò significa che si prendono tutte le decisioni di modifica mentre si chiama il comando e sed
esegue automaticamente le istruzioni., Questo può sembrare confuso o poco intuitivo, ma è un modo molto potente e veloce per trasformare il testo, soprattutto come parte di uno script o flusso di lavoro automatizzato.
Questo tutorial tratterà alcune operazioni di base e vi introdurrà alla sintassi necessaria per operare questo editor. Quasi certamente non sostituirai mai il tuo normale editor di testo con sed
, ma probabilmente diventerà un’aggiunta gradita alla tua casella degli strumenti di modifica del testo.
Nota: Questo tutorial utilizza la versione GNU di sed
trovato su Ubuntu e altri sistemi operativi Linux., Se stai usando macOS, avrai la versione BSD che ha diverse opzioni e argomenti. È possibile installare la versione GNU dised
con Homebrew utilizzandobrew install gnu-sed
.
Utilizzo di base
sed
opera su un flusso di testo che legge da un file di testo o da standard input (STDIN). Ciò significa che è possibile inviare l’output di un altro comando direttamente in sed per la modifica, oppure si può lavorare su un file che hai già creato.,
Dovresti anche essere consapevole che sed
emette tutto su standard out (STDOUT) per impostazione predefinita. Ciò significa che, a meno che non venga reindirizzato, sed
stamperà il suo output sullo schermo invece di salvarlo in un file.
L’utilizzo di base è:
- sed commands
In questo tutorial, si utilizzerà una copia della licenza Software BSD per sperimentare consed
., Su Ubuntu, eseguire i seguenti comandi per copiare la licenza BSD file nella directory home in modo da poter lavorare con:
- cd
- cp /usr/share/common-licenses/BSD .
Se non si dispone di una copia locale della licenza BSD, creare uno voi stessi con questo comando:
- cat << 'EOF' > BSD
- Copyright (c) The Regents of the University of California.
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
- EOF
usiamo sed
per visualizzare il contenuto del file di licenza BSD. sed
invia i suoi risultati allo schermo per impostazione predefinita, il che significa che puoi usarlo come lettore di file passando nessun comando di modifica., Prova a eseguire il seguente comando:
- sed '' BSD
Vedrai la licenza BSD visualizzata sullo schermo:
OutputCopyright (c) The Regents of the University of California.All rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditionsare met:1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.......
Le virgolette singole contengono i comandi di modifica che passi a sed
. In questo caso, non hai passato nulla, quindi sed
ha stampato ogni riga ricevuta allo standard output.
sed
può utilizzare lo standard input piuttosto che un file., Tubo di uscita di cat
comando sed
per produrre lo stesso risultato:
- cat BSD | sed ''
potrete vedere l’output del file:
OutputCopyright (c) The Regents of the University of California.All rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditionsare met:1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.. . .. . .
Come si può vedere, è in grado di operare su file o flussi di testo come quelli prodotti se la tubazione di uscita con il tubo (|)
carattere, proprio come facilmente.
Linee di stampa
Nell’esempio precedente, si è visto che l’input passato insed
senza alcuna operazione avrebbe stampato i risultati direttamente allo standard output.,
Esploriamosed
’s esplicitoprint
comando, che si specifica utilizzando ilp
tra virgolette singole.
Eseguire il seguente comando:
- sed 'p' BSD
potrete vedere ogni linea del BSD
file stampato due volte:
OutputCopyright (c) The Regents of the University of California.Copyright (c) The Regents of the University of California.All rights reserved.All rights reserved.Redistribution and use in source and binary forms, with or withoutRedistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditionsmodification, are permitted provided that the following conditionsare met:are met:. . .. . .
sed
stampa automaticamente ogni riga per impostazione predefinita, e poi hai detto che per la stampa di linee in modo esplicito con la “p” di comando, in modo che si ottiene ogni riga stampata due volte.,
Se esamini attentamente l’output, vedrai che ha la prima riga due volte, seguita dalla seconda riga due volte, ecc., che ti dice chesed
funziona su dati riga per riga. Legge una riga, opera su di essa e emette il testo risultante prima di ripetere il processo sulla riga successiva.
È possibile ripulire i risultati passando l’opzione -n
a sed
, che sopprime la stampa automatica:
- sed -n 'p' BSD
OutputCopyright (c) The Regents of the University of California.All rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditionsare met:1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.. . .. . .
Ora sono tornati a stampare ogni riga una volta.,
Gli esempi finora non possono essere considerati di modifica (a meno che tu non voglia stampare ogni riga due volte…). Successivamente esplorerai comesed
può modificare l’output mirando a sezioni specifiche dei dati di testo.
Utilizzando gli intervalli di indirizzi
gli indirizzi consentono di indirizzare parti specifiche di un flusso di testo. È possibile specificare una linea specifica o anche un intervallo di linee.
Facciamosed
stampare la prima riga del file., Eseguire il seguente comando:
- sed -n '1p' BSD
La prima riga di stampa di schermo:
OutputCopyright (c) The Regents of the University of California.
inserendo il numero 1
prima il comando di stampa, si disse sed
il numero di riga su cui operare. Puoi facilmente stampare cinque righe (non dimenticare “- n”):
- sed -n '1,5p' BSD
Vedrai questo output:
OutputCopyright (c) The Regents of the University of California.All rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions
Hai appena dato un intervallo di indirizzi a sed
., Se si dà un indirizzosed
, eseguirà solo i comandi che seguono su quelle righe. In questo esempio, hai detto a sed di stampare dalla riga 1 alla riga 5. Avresti potuto specificare questo in un modo diverso dando il primo indirizzo e quindi usando un offset per dire a sed quante linee aggiuntive percorrere, come questo:
- sed -n '1,+4p' BSD
Questo risulterà nello stesso output, perché hai detto a sed
di iniziare dalla riga 1 e quindi operare anche sulle successive 4 righe.,
Se si desidera stampare ogni altra riga, specificare l’intervallo dopo il carattere ~
. Il seguente comando stampa ogni altra riga nel file BSD
, iniziando dalla riga 1:
- sed -n '1~2p' BSD
Ecco l’output che vedrai:
OutputCopyright (c) The Regents of the University of California.modification, are permitted provided that the following conditions1. Redistributions of source code must retain the above copyright2. Redistributions in binary form must reproduce the above copyright documentation and/or other materials provided with the distribution. may be used to endorse or promote products derived from this software. . .. . .
Puoi usare sed
per eliminare anche il testo dall’output.,
Eliminazione del testo
È possibile eseguire l’eliminazione del testo dove in precedenza si specificava la stampa del testo modificando il comandop
nel comandod
.
In questo caso, non è più necessario il comando -n
perché sed
stamperà tutto ciò che non viene eliminato. Questo ti aiuterà a vedere cosa sta succedendo.,
Modifica l’ultimo comando della sezione precedente per farlo
cancellare ogni altra riga che inizia con la prima:
- sed '1~2d' BSD
Il risultato è che vedi ogni riga che non ti è stata data l’ultima volta:
OutputAll rights reserved.Redistribution and use in source and binary forms, with or withoutare met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the3. Neither the name of the University nor the names of its contributors without specific prior written permission.. . .. . .
È importante notare che il nostro file sorgente non è interessato. È ancora intatto. Le modifiche vengono inviate al nostro schermo.,
Se vogliamo salvare le nostre modifiche, siamo in grado di reindirizzare standard output su un file in questo modo:
- sed '1~2d' BSD > everyother.txt
aprire il file con cat
:
- cat everyother.txt
Si vede lo stesso risultato che si è visto sullo schermo in precedenza:
OutputAll rights reserved.Redistribution and use in source and binary forms, with or withoutare met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the3. Neither the name of the University nor the names of its contributors without specific prior written permission.. . .. . .
sed
comando non modifica il file di origine per impostazione predefinita, ma è possibile modificare questo comportamento, passando il -i
opzione, il che significa che “l’esecuzione di modifiche sul posto.”Questo altererà il file sorgente.,
Attenzione: Utilizzando il-i
interruttore sovrascriverà il file originale, quindi si dovrebbe usare questo con cura. Eseguire le operazioni senza prima l’interruttore-i
e quindi eseguire nuovamente il comando con-i
una volta ottenuto ciò che si desidera, creare un backup del file originale o reindirizzare l’output a un file. È molto facile alterare accidentalmente il file originale con l’opzione-i
.
Proviamo modificando il fileeveryother.txt
appena creato, sul posto., Riduciamo ulteriormente il file eliminando di nuovo ogni altra riga
:
- sed -i '1~2d' everyother.txt
Se usi cat
per visualizzare il file con cat everyother.txt
, vedrai che il file è stato modificato.
L’opzione -i
può essere pericolosa. Per fortuna, sed
ti dà la possibilità di creare un file di backup prima della modifica.,
Per creare un file di backup prima della modifica, aggiungere l’estensione di backup direttamente dopo l’opzione “-i”:
- sed -i.bak '1~2d' everyother.txt
Questo crea un file di backup con l’estensione .bak
, quindi modifica il file originale sul posto.
Successivamente vedrai come usaresed
per eseguire operazioni di ricerca e sostituzione.
Sostituzione del testo
Forse l’uso più noto persed
sta sostituendo il testo., sed
può cercare modelli di testo usando espressioni regolari e quindi sostituire il testo trovato con qualcos’altro.
Puoi saperne di più sulle espressioni regolari seguendo l’uso delle espressioni regolari Grep per cercare modelli di testo in Linux.
Nella sua forma più semplice, puoi cambiare una parola in un’altra parola usando la seguente sintassi:
's/old_word/new_word/'
Il s
è il comando sostitutivo. Le tre barre (/
) vengono utilizzate per separare i diversi campi di testo., È possibile utilizzare altri caratteri per delimitare i campi se sarebbe più utile.
Ad esempio, se si stesse tentando di cambiare il nome di un sito Web, l’utilizzo di un altro delimitatore sarebbe utile poiché gli URL contengono barre.
Eseguire il seguente comando per stampare un URL con echo
e modificare con sed
, utilizzando il carattere di sottolineatura (_
) come delimitatore:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'
Questo sostituisce com/index
con org/home
., L’output mostra l’URL modificato:
Output
Do not forget the final delimiter, or sed
will complain. If you ran this command:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home'
Vedrai questo output:
Outputsed: -e expression #1, char 20: unterminated `s' command
Creiamo un nuovo file per praticare alcune sostituzioni. Eseguire il seguente comando per creare un nuovo file di testo chiamato song.txt
:
- echo "this is the song that never ends
- yes, it goes on and on, my friend
- some people started singing it
- not knowing what it was
- and they'll continue singing it forever
- just because..." > song.txt
Ora sostituiamo l’espressioneon
conforward
. Usa il seguente comando:
- sed 's/on/forward/' song.txt
L’output è simile a questo:
Outputthis is the sforwardg that never endsyes, it goes forward and on, my friendsome people started singing itnot knowing what it wasand they'll cforwardtinue singing it foreverjust because...
Qui puoi vedere alcune cose notevoli., Innanzitutto, è chesed
ha sostituito i modelli, non le parole. Il on
all’interno di song
viene modificato in forward
.
L’altra cosa da notare è che sulla riga 2, il secondoon
non è stato modificato inforward
.
Questo perché per impostazione predefinita, il comando s
opera sulla prima corrispondenza di una riga e quindi passa alla riga successiva., Per renderesed
sostituire ogni istanza dion
invece della prima di ogni riga, è necessario passare un flag opzionale al comando substitute.
Fornire il flagg
al comando substitute posizionandolo dopo il set di sostituzione:
- sed 's/on/forward/g' song.txt
Vedrai questo output:
Outputthis is the sforwardg that never endsyes, it goes forward and forward, my friendsome people started singing itnot knowing what it wasand they'll cforwardtinue singing it foreverjust because...
Ora il comando substitute cambia ogni istanza.,
Se si voleva modificare la seconda istanza di “a” che sed trova su ogni linea, allora si dovrebbe utilizzare il numero 2
invece di g
:
- sed 's/on/forward/2' song.txt
Questa volta le altre linee sono rimaste invariate, in quanto non hanno una seconda ricorrenza:
Outputthis is the song that never endsyes, it goes on and forward, my friendsome people started singing itnot knowing what it wasand they'll continue singing it foreverjust because...
Se si desidera solo per vedere quali linee sono stati sostituiti, utilizzare il tag -n
nuovamente l’opzione per sopprimere la funzione di stampa automatica.,
È quindi possibile passare l’opzione p
al comando substitute per stampare le righe in cui è avvenuta la sostituzione.
- sed -n 's/on/forward/2p' song.txt
La riga che ha cambiato stampa sullo schermo:
Outputyes, it goes on and forward, my friend
Come puoi vedere, puoi combinare i flag alla fine del comando.
Se si desidera che il processo di ricerca ignori il caso, è possibile passare il flag “i”.,
- sed 's/SINGING/saying/i' song.txt
Ecco l’output che vedrai:
Outputthis is the song that never endsyes, it goes on and on, my friendsome people started saying itnot knowing what it wasand they'll continue saying it foreverjust because...
Sostituzione e riferimento del testo abbinato
Se vuoi trovare modelli più complessi con espressioni regolari, hai un certo numero di metodi diversi per fare riferimento al modello abbinato nel testo sostitutivo.,
per esempio, Per il match dall’inizio della riga at
, utilizzare il seguente comando:
- sed 's/^.*at/REPLACED/' song.txt
verrà visualizzato il seguente output:
Output REPLACED never endsyes, it goes on and on, my friendsome people started singing itREPLACED it wasand they'll continue singing it foreverjust because...
Si può vedere che il jolly espressione partite dall’inizio della linea per l’ultima istanza di at
.
Poiché non si conosce la frase esatta che corrisponderà nella stringa di ricerca, è possibile utilizzare il carattere&
per rappresentare il testo corrispondente nella stringa sostitutiva.,
Mettiamo parentesi attorno al testo abbinato:
- sed 's/^.*at/(&)/' song.txt
Vedrai questo output:
Output (this is the song that) never endsyes, it goes on and on, my friendsome people started singing it(not knowing what) it wasand they'll continue singing it foreverjust because...
Un modo più flessibile di fare riferimento al testo abbinato è usare parentesi con escape per raggruppare sezioni di testo abbinato.
Ogni gruppo di testo di ricerca contrassegnato da parentesi può essere referenziato da un numero di riferimento con escape. Ad esempio, il primo gruppo di parentesi può essere referenziato con \1
, il secondo con \2
e così via.,
In questo esempio, cambieremo le prime due parole di ogni riga:
- sed 's/\(*\) \(*\)/\2 \1/' song.txt
Vedrai questo output:
Output is this the song that never endsyes, goes it on and on, my friendpeople some started singing itknowing not what it wasthey and'll continue singing it foreverbecause just...
Come puoi vedere, i risultati non sono perfetti. Ad esempio, la seconda riga salta la prima parola perché ha un carattere non elencato nel nostro set di caratteri. Allo stesso modo, ha trattato they'll
come due parole nella quinta riga.
Miglioriamo l’espressione regolare per essere più precisi:
- sed 's/\(*\) \(*\)/\2 \1/' song.txt
Vedrai questo output:
Output is this the song that never endsit yes, goes on and on, my friendpeople some started singing itknowing not what it wasthey'll and continue singing it foreverbecause... just
Questo è molto meglio dell’ultima volta., Questo raggruppa la punteggiatura con la parola associata.
Si noti come ripetiamo l’espressione all’interno delle parentesi (una volta senza il carattere *
, e poi una volta con esso). Questo perché il carattere*
corrisponde al set di caratteri che viene prima di zero o più volte. Ciò significa che la corrispondenza con il carattere jolly sarebbe considerata una “corrispondenza” anche se il modello non viene trovato.
Per garantire che sed
trovi il testo almeno una volta, devi abbinarlo una volta senza il carattere jolly prima di utilizzare il carattere jolly.,
Conclusione
In questo tutorial hai esplorato il comandosed
. Hai stampato righe specifiche dal file, cercato testo, eliminato righe, sovrascritto il file originale e usato espressioni regolari per sostituire il testo. Dovresti essere in grado di vedere già come puoi trasformare rapidamente un documento di testo usando comandi sed costruiti correttamente.
Nel prossimo articolo di questa serie, potrete esplorare alcune caratteristiche più avanzate.