2017-12-29 38 views
1

Ich brauche Hilfe beim Ersetzen einer Zeichenfolge in einer Datei, wo "von" - "zu" Zeichenfolgen aus einer bestimmten Datei kommen.Ersetzen Zeichenfolge in einer Datei aus einer Datei

fromto.txt:

"TRAVEL","TRAVEL_CHANNEL" 
"TRAVEL HD","TRAVEL_HD_CHANNEL" 
"FROM","TO" 

Erste Spalte ist das, was ich für, bin auf der Suche, die mit der zweiten Spalte ersetzt werden soll.

Bisher habe ich dieses kleine Skript:

while read p; do 
    var1=`echo "$p" | awk -F',' '{print $1}'` 

    var2=`echo "$p" | awk -F',' '{print $2}'` 
    echo "$var1" "AND" "$var2" 

    sed -i -e 's/$var1/$var2/g' test.txt 
done <fromto.txt 

Ausgabe sieht gut aus (x und y), aber aus irgendeinem Grund ist es nicht die erste Spalte ($ var1) mit dem zweiten ($ var2) ersetzen .

test.txt:

"TRAVEL" 

Ausgang:

"TRAVEL" AND "TRAVEL_CHANNEL" 
sed -i -e 's/"TRAVEL"/"TRAVEL_CHANNEL"/g' test.txt 
"TRAVEL HD" AND "TRAVEL_HD_CHANNEL" 
sed -i -e 's/"TRAVEL HD"/"TRAVEL_HD_CHANNEL"/g' test.txt 
"FROM" AND "TO" 
sed -i -e 's/"FROM"/"TO"/g' test.txt 

$ cat test.txt 
"TRAVEL" 
+1

Um Ihnen den Einstieg zu erleichtern, arbeitet 'sed -i' direkt an einer Datei. Jetzt müssen Sie nur die Befehle für 'sed' herausfinden :) – bedwyr

+0

Ja, ich kann sed Befehl vor jeder Zeile hinzufügen, aber die tatsächliche" fromto.txt "ist ziemlich groß. Es ist irgendwie möglich, diese Variablen/Argumente für sed aus einer Datei zu lesen? – Adrian

+0

Das ist eine hilfreiche Klarstellung - es ist nicht sofort aus der Beschreibung ersichtlich. So wie ein einfaches Rezept (dies kann von der Shell-Eingabeaufforderung durchgeführt werden): 1. für jede Zeile in der Datei; 2. Teilen Sie die Linie, extrahieren Sie die Werte zwischen den ""; 3. Verwenden Sie diese Werte in einem "sed" -Befehl zum Ersetzen (zB 'sed -i 's/$ val1/$ val2/g'') Sinn machen? – bedwyr

Antwort

0

Sie diese oneshot nicht tun können Sie Variablen in einem Skript

vielleicht so etwas wie unten sed verwenden müssen Befehl für den vollständigen Austausch

-bash-4.4$ cat > toto.txt 
1 
2 
3 
-bash-4.4$ cat > titi.txt 
a 
b 
c 
-bash-4.4$ sed 's|^\s*\(\S*\)\s*\(.*\)$|/^\2\\>/s//\1/|' toto.txt | sed -f - titi.txt > toto.txt 
-bash-4.4$ cat toto.txt 
a 
b 
c 
-bash-4.4$ 
1

Eingang:

➜ cat fromto 
TRAVEL TRAVEL_CHANNEL 
TRAVELHD TRAVEL_HD 
➜ cat inputFile 
TRAVEL 
TRAVELHD 

Die Arbeit:

➜ awk 'BEGIN{while(getline < "fromto") {from[$1] = $2}} {for (key in from) {gsub(key,from[key])} print}' inputFile > output 

und Ausgang:

➜ cat output 
TRAVEL_CHANNEL 
TRAVEL_CHANNEL_HD 
➜ 

dieser ersten (BEGIN{}) lädt Ihre Eingabedatei in ein assoziatives Array: from["TRAVEL"] = "TRAVEL_HD", dann führt für jedes Array-Element in der Eingabe f Zeile für Zeile ziemlich ineffizient durch Ich gebe die Ergebnisse aus, die ich an eine separate Ausgabedatei weitergeleitet habe.

Der Nachteil, Sie werden feststellen, ist, dass die Suche und ersetzen einander stören können, die zweite Zeile der Ausgabe ist ein perfektes Beispiel, da der erste Austausch passiert. Sie können versuchen, Ihre Ersetzungen anders zu bestellen oder eine Regex anstelle von gsub zu verwenden. Ich bin mir nicht sicher, ob awk-Arrays garantiert eine bestimmte Reihenfolge haben. Irgendwie, um dich zu fangen.

2. Vorbehalt. Es gibt einen Weg, den gsub für die ganze Datei als den zweiten Schritt Ihres BEGIN zu machen und das wahrscheinlich viel schneller zu machen, aber ich bin mir nicht sicher, was es ist.

+1

Great one Liner, aber das Format von fromto ist mehr oder weniger fest. Es gibt Anführungszeichen, die wegen Strings mit Leerzeichen verwendet werden, zB "DISCOVERY CHANNEL". – Adrian

+1

@Adrian - Ah, ich denke das kann mit 'patsplit()' gelöst werden und sowas von hier: https://www.gnu.org/software/gawk/manual/gawk.html#Splitting-By-Content aber Wir nähern uns einem vernünftigen Limit für Einzeiler (und meine Fähigkeiten mit Awk), denke ich :) – zzxyz

Verwandte Themen