2016-10-09 2 views
3

Ich möchte eine große Textdatei Zeile für Zeile suchen und jeden Eintrag mit "N:;;" finden und einfach in "N:07401000000;;" ändern und dann das nächste Vorkommen von "N:;;" würde in "N:07401000002;;" geändert werden und so weiter in der gesamten Datei der Einträge. Hier ist ein Beispiel von vorher und nachher.Bash, Awk, Sed? Find Zeichenkette innerhalb der Datei und fügt Ziffern innerhalb der Zeichenkette an?

Vorher:

BEGIN:VCARD 
VERSION:2.1 
N:;; 
TEL;TYPE=CELLVOICE:07401000000 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:;; 
TEL;TYPE=CELLVOICE:07401000001 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:;; 
TEL;TYPE=CELLVOICE:07401000002 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:;; 
TEL;TYPE=CELLVOICE:07401000003 
END:VCARD 

Nach Ergebnis würde wie folgt aussehen:

BEGIN:VCARD 
VERSION:2.1 
N:07401000000;; 
TEL;TYPE=CELLVOICE:07401000000 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000001;; 
TEL;TYPE=CELLVOICE:07401000001 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000002;; 
TEL;TYPE=CELLVOICE:07401000002 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000003;; 
TEL;TYPE=CELLVOICE:07401000003 
END:VCARD 

Jede Hilfe oder Ideen wäre genial.

Möchten Sie, dass die Werte N bei einem hartcodierten Wert beginnen und inkrementieren oder einfach den Wert aus dem nachfolgenden CELLVOICE kopieren?

Eigentlich ist das eine gute Idee. Wie wäre es mit dem in CELLVOICE genannten Wert?

+0

WOW, das ist eigentlich eine gute Idee .. wie über den Wert Erwähnungen in CELLVOICE .. –

Antwort

2

Hier ist das robusteste und leicht erweiterbare Weise zu tun, was Sie wollen:

$ cat tst.awk 
BEGIN { RS="END:VCARD\\s*"; FS="\n"; OFS=":" } 
{ 
    $0 = $0 gensub(/\s+$/,"",1,RT) 

    for (i=1; i<=NF; i++) { 
     name = gensub(/:.*/,"",1,$i) 
     value = gensub(/.*:/,"",1,$i) 
     n2v[name] = value 
     names[i] = name 
    } 

    n2v["N"] = n2v["TEL;TYPE=CELLVOICE"] n2v["N"] 

    for (i=1; i<=NF; i++) { 
     name = names[i] 
     value = n2v[name] 
     print name, value 
    } 
} 

.

$ awk -f tst.awk file 
BEGIN:VCARD 
VERSION:2.1 
N:07401000000;; 
TEL;TYPE=CELLVOICE:07401000000 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000001;; 
TEL;TYPE=CELLVOICE:07401000001 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000002;; 
TEL;TYPE=CELLVOICE:07401000002 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000003;; 
TEL;TYPE=CELLVOICE:07401000003 
END:VCARD 

Die oben verwendet GNU awk für gensub(), multi-char RS und RT und einfach (und idiomatischen) Idee ist es, die Eingabe in Sätze aufgeteilt, die mit END:VCARD und für jeden Datensatz Ende zuerst ein Array erstellen (n2v[]), die Feldnamen (der Teil vor dem ersten : auf jeder Zeile) ihren Werten zuordnet (der Teil nach dem ersten :) und dann können Sie einfach jedes Feld durch seinen Namen manipulieren, so können Sie Werte trivial ändern, die Reihenfolge neu anordnen, Standardeinstellungen, usw. usw.

+0

[Didge @ vosser 07401] $ awk tst master07401.vcf [Didge @ vosser 07401] $ tst master07401.vcf bash: tst: Befehl nicht gefunden [Didge @ vosser 07401] $ bash tst master07401.vcf tst: Linie 1: BEGIN: Befehl nicht gefunden tst: Linie 1:}: Befehl nicht tst gefunden: Zeile 3: Syntaxfehler nahe dem unerwarteten Token '(' tst: Zeile 3:' $ 0 = $ 0 gensub (/ \ s + $ /, "", 1, RT)' [Didge @ vosser 07401] $ Leite ich das Skript nicht korrekt? –

+1

löste es, Vielen Dank Ed Morton, ich habe es nicht richtig gelesen .. mein schlechtes und tut mir leid für die RTFM kommt in den Sinn und Sie sind dann willkommen, mich mit einer nassen Forelle schlagen: D –

0

Ed Mortons Antwort ist compre sendes, aber wenn Sie für eine schnelle Lösung suchen, das auch die Arbeit erledigt:

$ awk 'BEGIN {N=07401000000} /N:;;/ {print "N:"N++";;"; next} 1' myfile.vcf 
+0

Wie gehe ich um Ich habe versucht, script.sh myfile.vcf –

+0

Sie tun 'awk-f script.awk myfile.vcf' – chthonicdaemon

0

die Linien Unter der Annahme, mit N:;; und CELLVOICE zueinander auftreten nächste wie in der Probe gezeigt, hier ist eine Lösung mit sed

$ sed -E '/N:;;/{N;s/.*\n(.*CELLVOICE:([0-9]+))/N:\2;;\n\1/}' ip.txt 
BEGIN:VCARD 
VERSION:2.1 
N:07401000000;; 
TEL;TYPE=CELLVOICE:07401000000 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000001;; 
TEL;TYPE=CELLVOICE:07401000001 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000002;; 
TEL;TYPE=CELLVOICE:07401000002 
END:VCARD 
BEGIN:VCARD 
VERSION:2.1 
N:07401000003;; 
TEL;TYPE=CELLVOICE:07401000003 
END:VCARD 
  • Wenn die Muster /N:;;/ Streichhölzer, nächste Zeile erhalten mit N
  • Dann Substitution durchführen, wie pro erforderliche Format, \n trennt die beiden Linien


Lösung mit perl wird gesamte Eingabedatei als eine große Zeichenfolge schlürft und dann Substitution durchgeführt

perl -0777 -pe 's/N:;;\n(.*CELLVOICE:(\d+))/N:$2;;\n$1/g' ip.txt 
Verwandte Themen