Trova e sostituisci il testo all'interno di un file usando i comandi


Risposte:


1053
sed -i 's/original/new/g' file.txt

Spiegazione:

  • sed = Stream EDitor
  • -i = sul posto (ad es. salvare di nuovo nel file originale)
  • La stringa di comando:

    • s = il comando sostitutivo
    • original = un'espressione regolare che descrive la parola da sostituire (o solo la parola stessa)
    • new = il testo con cui sostituirlo
    • g = globale (ovvero sostituire tutto e non solo la prima occorrenza)
  • file.txt = il nome del file


3
@Akiva Se includi i caratteri speciali regex nella tua ricerca sed, li corrisponderanno. Aggiungi un -rflag se vuoi usare invece RE estese.
cscarney,

32
@mcExchange Se è specificamente il /personaggio che devi abbinare, puoi semplicemente usare qualche altro personaggio come separatore (es 's_old/text_new/text_g'.). Altrimenti, puoi mettere un punto \ qualsiasi $ * . [ \ ^per ottenere il personaggio letterale.
cscarney,

3
@BrianZ Per quanto riguarda il file system, l'output di sed è un nuovo file con lo stesso nome. È uno dei bug comunemente segnalati che non sono bug
cscarney,

17
Il comando OSX sed -i '.bak' 's/original/new/g' file.txtpuò anche essere eseguito con un'estensione di lunghezza zero sed -i '' 's/original/new/g' file.txt, che non genererà alcun backup.
Kirk,

20
Gli utenti MacOS dovranno aggiungere '' "dopo -i come parametro per -i ed.gs/2016/01/26/os-x-sed-invalid-command-code in modo che il file venga sovrascritto.
geoyws

32

Esistono diversi modi per farlo. Uno sta usando sede Regex. SED è uno Stream Editor per filtrare e trasformare il testo. Un esempio è il seguente:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog

Un altro modo che può avere più senso di < strined > stroutè con i tubi!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai 
The quick brown fox jumped over the lazy sleeping dog

6
si noti che catin cat file | sed '...'non è necessario. Puoi dirlo direttamente sed '...' file.
fedorqui,

1
In effetti, questo può essere ulteriormente ridotto: sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarlyprenderà il file l'anno e farà le 2 modifiche sul posto mentre si esegue un backup. Usando il time bash -c "$COMMAND"tempo suggerisce che questa versione è ~ 5 volte più veloce.
pbhj,

23

Ci sono molti modi per raggiungerlo. A seconda della complessità di ciò che si cerca di ottenere con la sostituzione delle stringhe e in base agli strumenti con cui l'utente ha familiarità, alcuni metodi potrebbero essere preferiti più di altri.

In questa risposta sto usando un input.txtfile semplice , che puoi usare per testare tutti gli esempi forniti qui. Il contenuto del file:

roses are red , violets are blue
This is an input.txt and this doesn't rhyme

BASH

Bash non è realmente pensato per l'elaborazione del testo, ma semplici sostituzioni possono essere fatte tramite l' espansione dei parametri , in particolare qui possiamo usare una struttura semplice ${parameter/old_string/new_string}.

#!/bin/bash
while IFS= read -r line
do
    case "$line" in
       *blue*) printf "%s\n" "${line/blue/azure}" ;;
       *) printf "%s\n" "$line" ;;
    esac
done < input.txt

Questo piccolo script non esegue la sostituzione sul posto, il che significa che dovresti salvare il nuovo testo in un nuovo file e sbarazzarti del vecchio file, oppure mv new.txt old.txt

Nota a margine: se sei curioso di sapere perché while IFS= read -r ; do ... done < input.txtviene utilizzato, è fondamentalmente il modo di shell di leggere il file riga per riga. Vedi questo per riferimento.

AWK

AWK, essendo un'utilità di elaborazione del testo, è abbastanza appropriato per tale compito. Può fare sostituzioni semplici e molto più avanzate basate su espressioni regolari . Offre due funzioni: sub()e gsub(). Il primo sostituisce solo la prima occorrenza, mentre il secondo sostituisce le occorrenze nell'intera stringa. Ad esempio, se abbiamo stringa one potato two potato, questo sarebbe il risultato:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana

$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      
one banana two potato 

AWK può prendere un file di input come argomento, quindi fare le stesse cose con input.txtsarebbe facile:

awk '{sub(/blue/,"azure")}1' input.txt

A seconda della versione di AWK in uso, è possibile che sia presente o meno una modifica sul posto, pertanto la pratica abituale è salvare e sostituire il nuovo testo. Ad esempio qualcosa del genere:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed è un editor di linee. Utilizza anche espressioni regolari, ma per semplici sostituzioni è sufficiente:

sed 's/blue/azure/' input.txt

La cosa positiva di questo strumento è che ha una modifica sul posto, che puoi abilitare con -iflag.

Perl

Perl è un altro strumento che viene spesso utilizzato per l'elaborazione del testo, ma è un linguaggio generico e viene utilizzato in rete, amministrazione di sistema, app desktop e molti altri luoghi. Ha preso in prestito molti concetti / caratteristiche da altri linguaggi come C, sed, awk e altri. La sostituzione semplice può essere effettuata in questo modo:

perl -pe 's/blue/azure/' input.txt

Come sed, perl ha anche la bandiera -i.

Pitone

Questo linguaggio è molto versatile ed è utilizzato anche in un'ampia varietà di applicazioni. Ha molte funzioni per lavorare con le stringhe, tra le quali è replace(), quindi se hai variabili simili var="Hello World", potresti farlovar.replace("Hello","Good Morning")

Il modo semplice per leggere il file e sostituire la stringa in questo modo sarebbe:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

Con Python, tuttavia, devi anche eseguire l'output in un nuovo file, cosa che puoi fare anche dallo script stesso. Ad esempio, eccone uno semplice:

#!/usr/bin/env python
import sys
import os
import tempfile

tmp=tempfile.mkstemp()

with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
    for line in fd1:
        line = line.replace('blue','azure')
        fd2.write(line)

os.rename(tmp[1],sys.argv[1])

Questo script deve essere chiamato input.txtcome argomento da riga di comando. Il comando esatto per eseguire lo script Python con l'argomento della riga di comando sarebbe

 $ ./myscript.py input.txt

o

$ python ./myscript.py input.txt

Naturalmente, assicurati che ./myscript.pysia nella tua directory di lavoro corrente e, per la prima volta, assicurati che sia impostato eseguibile conchmod +x ./myscript.py

Python può anche avere espressioni regolari, in particolare c'è un remodulo, che ha una re.sub()funzione, che può essere usato per sostituzioni più avanzate.


1
Bella compilation! Un altro possibile modo non menzionato qui è l'utilizzo del trcomando in unix
Tapajit Dey

1
@TapajitDey Sì, tr è un altro ottimo strumento, ma nota che è per sostituire gruppi di caratteri (ad esempio, tr abc cdesi tradurrebbe ain c, ba d. È un po 'diverso dalla sostituzione di parole intere come con sedopython
Sergiy Kolodyazhnyy

22

Puoi usare Vim in modalità Ex:

ex -s -c '%s/OLD/NEW/g|x' file
  1. % seleziona tutte le righe

  2. s sostituto

  3. g sostituire tutte le istanze in ciascuna riga

  4. x scrivere se sono state apportate modifiche (hanno) e uscire


21

Tramite il comando gsub di awk,

awk '{gsub(/pattern/,"replacement")}' file

Esempio:

awk '{gsub(/1/,"0");}' file

Nell'esempio sopra, tutti gli 1 sono sostituiti da 0 indipendentemente dalla colonna in cui si trova.


Se vuoi fare una sostituzione su una colonna specifica, quindi fai così,

awk '{gsub(/pattern/,"replacement",column_number)}' file

Esempio:

awk '{gsub(/1/,"0",$1);}' file

Sostituisce 1 con 0 solo nella prima colonna.

Attraverso Perl,

$ echo 'foo' | perl -pe 's/foo/bar/g'
bar

L'ho usato sul terminale MacOS e non ha fatto nulla ...
Jim,

Testato su Alpine Linux (nel contenitore Docker) e nessun output
Salathiel Genèse

@ SalathielGenèse cosa stai cercando di ottenere?
Avinash Raj,

Sto guardando file con inotifywaitunder shenv e riportando i dati in formato CSV (perché il formato personalizzato è difettoso). Ho quindi pensato che non esiste un modo semplice per gestire il documento CSV negli script di shell ... E lo voglio molto leggero. Quindi ho iniziato uno script abbastanza semplice per analizzare e segnalare CSV. Ho letto le specifiche CSV e ho notato che è più elaborato di quanto mi aspettassi e supporta il valore multilinea racchiuso tra virgolette doppie. sedFacevo affidamento sulla tokenizzazione ma presto mi sono reso conto che anche ciò che sedchiamano multiline è fino a due righe. Cosa succede se uno dei miei valori CSV si estende su più di due righe?
Salathiel Genèse,

meglio porre il tuo problema come una domanda.
Avinash Raj,

8

sedè il s tream ed itor , in quanto è possibile utilizzare |(pipe) per inviare flussi standard (STDIN e STDOUT in particolare) attraverso sede modificare a livello di codice al volo, che lo rende uno strumento utile nella tradizione filosofia Unix; ma può anche modificare direttamente i file, usando il -iparametro menzionato di seguito.
Considera quanto segue :

sed -i -e 's/few/asd/g' hello.txt

s/è usato per s ubstitute l'espressione trovata fewcon asd:

I pochi, i coraggiosi.


Il asd, il coraggioso.

/gsta per "globale", che significa farlo per l'intera linea. Se si interrompe il /g(con s/few/asd/, ci devono sempre essere tre barre a prescindere) e fewappare due volte sulla stessa linea, solo la prima fewviene cambiata in asd:

I pochi uomini, le poche donne, i coraggiosi.


Gli uomini asd, le poche donne, i coraggiosi.

Ciò è utile in alcune circostanze, come la modifica di caratteri speciali all'inizio delle righe (ad esempio, la sostituzione dei simboli maggiore di quelli che alcune persone usano per citare il materiale precedente nei thread di posta elettronica con una scheda orizzontale lasciando una disuguaglianza algebrica citata più avanti nella riga intatto), ma nel tuo esempio in cui specifichi che dovunque si few verifichi dovrebbe essere sostituito, assicurati di averlo /g.

Le seguenti due opzioni (flag) sono combinate in una sola -ie:

-iopzione viene utilizzata per modificare i n immettere sul file hello.txt.

-eopzione indica la posta Xpression / comando da eseguire, in questo caso s/.

Nota: è importante utilizzare -i -eper cercare / sostituire. In tal caso -ie, si crea un backup di ogni file con la lettera 'e' allegata.


2

Puoi fare così:

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

Esempi: per sostituire tutte le occorrenze [logdir ',' '] (senza []) con [logdir', os.getcwd ()] in tutti i file risultanti dal comando di individuazione, eseguire:

EX1:

locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"

EX2:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

dove [tensorboard / program.py] è il file da cercare


Ciao. La scelta delle stringhe ( logdir', ''-> /logdir', os.getcwd()) rende questa risposta difficile da analizzare. Inoltre, vale la pena specificare che la tua risposta individua prima i file su cui utilizzare sed, perché non fa parte della domanda.
mwfearnley,

Ciao, questa risposta è sia la ricerca che la sostituzione di tutte se ha trovato <vecchio testo> nel file.
Nguyễn Tuấn Anh,

Scelgo questa risposta per tutto quello che usano tensorboard in keras, che vogliono cambiare il comando da: tensorboard --logdir = '/ path / to / log / folder /' da usare: solo tensorboard, quando rimani nella cartella dei log. è molto conveniente
Nguyễn Tuấn Anh
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.