GNU/Linux >> Linux Esercitazione >  >> Linux

Sostituzione di stringhe usando un dizionario?

Qual è un buon modo per sostituire le stringhe in un file usando un dizionario con molto di coppie sostituente-sostituente? E di molto , in realtà intendo circa 20, non molti, ma abbastanza da poterli organizzare ordinatamente.

Vorrei raccogliere tutte le coppie sostituente-sostituente in un file dictionary.txt in un modo facile da gestire, dal momento che ho bisogno di sostituire molte cose, dì come:

"yes"      : "no"
"stop"     : "go, go, go!"
"wee-ooo"  : "ooooh nooo!"
"gooodbye" : "hello"

"high"     : "low"
"why?"     : "i don't know"

Ora voglio applicare queste sostituzioni in alcuni file novel.txt .

Quindi voglio eseguire magiccommand --magicflags dictionary.txt novel.txt in modo che tutte le istanze di yes in novel.txt sono sostituiti da no (quindi anche Bayesian verrebbe sostituito da Banoian ) e tutte le istanze di goodbye in novel.txt verrebbe sostituito da hello e così via.

Finora, le stringhe che devo sostituire (e sostituire con) non contengono virgolette (né singole né doppie). (Sarebbe bello, tuttavia, vedere una soluzione che funziona bene con stringhe contenenti virgolette, ovviamente.)

Conosco sed e awk / gawk possono fare queste cose principalmente, ma possono anche funzionare con tali file di dizionario? Sembra gawk sarebbe il candidato giusto per magiccommand , quali sono i magicflags corretti ? Come devo formattare il mio dictionary.txt ?

Risposta accettata:

Ecco un modo con sed :

sed '
s|"(.*)"[[:blank:]]*:[[:blank:]]*"(.*)"|1
2|
h
s|.*n||
s|[&/]|\&|g
x
s|n.*||
s|[[.*^$/]|\&|g
G
s|(.*)n(.*)|s/1/2/g|
' dictionary.txt | sed -f - novel.txt

Come funziona:
Il primo sed trasforma dictionary.txt in un file di script (comandi di modifica, uno per riga). Questo viene inviato al 2° sed (notare il -f - il che significa leggere i comandi da stdin ) che esegue quei comandi, modificando novel.txt .
Ciò richiede la traduzione del formato

"STRING"   :   "REPLACEMENT"

in un sed comando e l'escape di qualsiasi carattere speciale nel processo sia per LHS e RHS :

s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g

Quindi la prima sostituzione

s|"(.*)"[[:blank:]]*:[[:blank:]]*"(.*)"|1
2|

trasforma "STRING" : "REPLACEMENT" in STRINGnREPLACEMENT (n è un carattere di nuova riga). Il risultato viene quindi copiato su h vecchio spazio.
s|.*n|| cancella la prima parte mantenendo solo REPLACEMENT quindi s|[&/]|\&|g esce dai caratteri riservati (questo è il RHS ).
Quindi ex cambia il buffer di attesa con lo spazio del pattern e s|n.*|| cancella la seconda parte mantenendo solo STRING e s|[[.*^$/]|\&|g fa l'escape (questo è il LHS ).
Il contenuto del buffer di attesa viene quindi aggiunto allo spazio del pattern tramite G quindi ora il contenuto dello spazio del modello è ESCAPED_STRINGnESCAPED_REPLACEMENT .
La sostituzione finale

s|(.*)n(.*)|s/1/2/g|

lo trasforma in s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g


Linux
  1. Avvolgi il primo carattere di una stringa usando Sed?

  2. Usa Sed per aggiungere il carattere nell'ennesima posizione della stringa corrispondente?

  3. Dividere i singoli caratteri usando la stringa nulla?

  4. Come scrivere più stringhe di righe usando Bash con variabili?

  5. Utilizzo di grep per cercare una stringa contenente un punto

Come creare un'istanza RDS utilizzando Python Boto3 su AWS

Utilizzo del comando Diff per confrontare due file nel terminale Linux

Bash Beginner Series #4:Utilizzo di array in Bash

Utilizzo del comando Bash printf per la stampa di output formattati

Come inviare una stringa al server utilizzando s_client

Come faccio a sapere se una macchina remota utilizza Windows o Linux?