2016-04-23 4 views
0

ich eine Textdatei mit folgendem Format haben:definieren Felder durch Leerzeichen, Anführungszeichen oder Klammern in gawk

RANDOM-WORD1 ==> "string with whitespaces" (string with whitespaces) 
RANDOM-WORD2 ==> "another string" (and another) 
RANDOM-WORD3 ==> "yet another string" (and another) 

Ich möchte durch die gawk Trennzeichen definieren:

  • Whitespaces
  • Zitate
  • Klammern

Zum Beispiel Zeile 1:

$1: RANDOM-WORD1 
$2: ==> 
$3: "string with whitespaces" 
$4: (string with whitespaces) 

Ich habe gawk ‚s FPATmanual gelesen und ich habe diese geschrieben:

FPAT = "([^[:blank:]]*)|(\"[^\"]+\")|(\([^)]+\))" 

Es ist jedoch nicht für die Klammern nicht funktioniert, wie ich:

Ich habe versucht, die Klammern in der dritten Klausel zu entkommen, aber es wird auch nicht funktionieren. Ich möchte jedes Zeichen ignorieren, das kein ) in einem Paar (...) ist. Ich weiß, dass es keine verschachtelten Klammern geben wird.

NB: Wie kann ich auch die Anführungszeichen/Klammern als Felddaten ignorieren? Zum Beispiel:

$1: RANDOM-WORD1 
$2: ==> 
$3: string with whitespaces 
$4: string with whitespaces 

Antwort

1

Wie für die Klammern, müssen Sie sie entkommen zweimal:

FPAT = "([^[:blank:]]*)|(\"[^\"]+\")|(\\([^\\)]+\\))" 

zu befreien von Klammern und Anführungszeichen zu erhalten, verwenden substr:

$3 = substr($3, 2, length($3) - 2); 
$4 = substr($4, 2, length($4) - 2); 
+0

Danke, das hat funktioniert. Ich habe auch den Grund dafür herausgefunden : https://stackoverflow.com/questions/11383643/groovy-why-doe-i-need-to-double-escape-square-brackets, ist es ein ähnlicher Fall? – Adama

+0

@Adama siehe http://StackOverflow.com/a/36806066/1745001, warum du sie zweimal meiden musst, sonst kannst du '[^ [: blank:]]' durch '\\ S' ersetzen, da du sowieso gawk benutzt. –

+1

@Adama In meinem Verständnis interpretiert 'awk' die Zeichenfolge vor dem Aufruf der Regex-Verarbeitungs-Engine. Nach den [Spezifikationen] (http://pubs.opengroup.org/onlinepubs/009695399/utilities/awk.html#tag_04_06_13_04) ist '\ (' keine gültige Escape-Sequenz, die in der Tabelle der Spezifikation aufgeführt ist. Das ist auch die Grund, warum gawk den Fehler "Warnung: Escape-Sequenz '\)' als unbehandelt ')'" anzeigt. Das '\ (' 'schafft es nie in die Regex - Engine. Um das zu erreichen, müssen Sie den umgekehrten Schrägstrich als \\ umgehen, damit er die String - Verarbeitung übergibt und die Regex - Engine' \ ('. – Guido

1

Diese FPAT = "([^ ]+)|([(][^)]+[)])|(\"[^\"]+\")" funktioniert für mich. Es nutzt den Trick, dass innerhalb [ ] die ( und ) brauchen nicht zu zitieren.

Bezüglich Ihrer zweiten Frage über die Anführungszeichen oder die Klammer Strippen, ich habe keine bessere Idee, als eine Aktion wie folgt ergänzt:

{ for(i=1; i<= NF; i++) { 
    b = substr($i, 1, 1); 
    e = substr($i, length($i), 1); 
    if((b == "\"" || b == "(") && (b == e)) { 
     $i = substr($i,2 , length($i) - 2) 
    } 
    } 
} 
+0

Vielen Dank für Ihr Feedback. :) Das "Double Escape" ist ein bisschen konsistenter mit den anderen beiden Klauseln, also werde ich damit gehen, aber ich werde diesen Trick auch behalten. – Adama

0

Ich würde FPAT dafür nicht verwenden, da es eine Reihenfolge für Ihre Felder gibt, nicht nur ein Muster. Ich würde die 3. arg verwenden übereinstimmen(), wie es ist einfacher und robuster:

match($0,/(\S+)\s(\S+)\s"([^"]+)"\s\(([^)]+).*/,a) 

z.B .:

$ awk 'match($0,/(\S+)\s(\S+)\s"([^"]+)"\s\(([^)]+).*/,a) { print; for (i=1; i in a; i++) printf "a[%d]: %s\n", i, a[i] }' file 
RANDOM-WORD1 ==> "string with whitespaces" (string with whitespaces) 
a[1]: RANDOM-WORD1 
a[2]: ==> 
a[3]: string with whitespaces 
a[4]: string with whitespaces 
RANDOM-WORD2 ==> "another string" (and another) 
a[1]: RANDOM-WORD2 
a[2]: ==> 
a[3]: another string 
a[4]: and another 
RANDOM-WORD3 ==> "yet another string" (and another) 
a[1]: RANDOM-WORD3 
a[2]: ==> 
a[3]: yet another string 
a[4]: and another 
Verwandte Themen