2017-02-13 5 views
1

Ich versuche eine riesige Datei (+5.000.000 Datensätze) zu manipulieren, so kann ich den Wert der 8. Spalte zum Beispiel ersetzen.Ersetzen Zeichenfolge durch einen neuen Wert

If $8 = 1 replace it with success 
if $8 = 2 replace it with check 
if $8 = null replace with undefined 

Hier ist ein Stück der Daten, die von einem , Zeichen getrennt ist:

"APPLICATION_ID","ORIGIN_ID","SERVICE_ID","PROVIDER_ID","RATING_ID","ATO","DATE","USER_TYPE","ESTATUS","OPERATION_ID" 

"3","2","424","5020","1058","3017292917","30/11/2016 01:14:25 a.m.","1","2004","14804862360104011458" 

Das Feld I ersetzt werden soll ist USER_TYPE$8

bei gelegen ich das versucht, aber es doesn‘ t ersetzen Sie die Werte:

awk '{if($8 = 1) print $1, $2, $3, $4, $5, $6, $7, "success", $9, $10}' input_file 

Wie kann ich das schaffen?

+0

wie unten ein einzelnen '=' weisen den Wert auf der RHS auf den Namen auf der LHS. Um auf Gleichheit zu prüfen, benutze '==', also 'if ($ 8 == 1) ...'. Sie müssen auch 'awk' sagen, um Felder auf dem', 'char zu teilen, entweder mit awk -F, '{...}' Datei' ODER' awk 'BEGIN {FS = ","} {.... } 'Datei'. Was passiert, wenn '' 'in den dbl-zitierten Daten stehen? Kaboom! ... So viel besser, ein Char zu verwenden, um Felder in Ihrer Datendatei zu trennen (oder vielleicht '|' char). Viel Glück. – shellter

+0

Wenn Sie mit CSV umgehen müssen, ist awk definitiv nicht der beste Weg, da es keine Fälle behandelt, in denen der Wert das Trennzeichen enthält. Sie sollten ein Werkzeug verwenden, das entwickelt wurde, um mit CSV umzugehen, zum Beispiel 'csvtool'. –

Antwort

0

Hier ist eine kürzere Einzeiler:

$ awk 'BEGIN{FS=OFS=",";a[1]="success";a[2]="check"} {gsub(/"/,"",$8)} $8 in a{$8=a[$8]} 1' input.txt 

ausgebrochenen zur Kommentierung:

BEGIN { 
    FS=OFS=","  # set our field separators 
    a[1]="success" # populate an array with replacement values 
    a[2]="check" 
} 

{ 
    gsub(/"/,"",$8) # remove quotes in field 8, for easier processing 
} 

$8 in a {   # check to see if field 8 is a member of our array 
    $8=a[$8]   # replace field 8 with the contents of the array at that index 
} 

1     # print the line 

Wenn es wichtig ist, um jedes Feld die Zitate zu halten, können Sie das tun, indem Sie die Zuweisung mit einem sprintf() ersetzen das schließt sie ein:

Denken Sie daran, dass awk nur über Ihren Feldtrenner weiß, nicht Ihre Angebote. Wenn Sie ein Feld mit einem Komma im Feld in Anführungszeichen haben, wird es von awk als Feldtrennzeichen betrachtet. Sie könnten Schutz für diese Art von Vorkommen mit so etwas wie diesem an der Spitze der awk-Skript hinzu:

NF != 10 { print "ERROR: wrong number of fields in line",NR > "/dev/stderr"; exit(1) } 
+0

direkt auf das Geld, es funktioniert perfekt, vielen Dank :) – sandatomo

+0

Yay, froh, ich könnte helfen! :) (Ich frage mich, wer aber ohne einen Kommentar abgelehnt hat.) – ghoti

1

@sandatomo: Versuchen (nicht getestet):

awk -F, -vs1="\"" 'NR>1{gsub(/\"/,"",$8);if($8==1){sub(/.*/,s1 "success" s1,$8)};if($8==2){sub(/.*/,s1 "check" s1,$8)};if($8=="null"){sub(/.*/,s1 "undefined" s1,$8)};print}' OFS=, Input_file 

EDIT: jetzt auch eine nicht einzeiler Form einer Lösung hinzuzufügen.

EDIT2: Ich habe meinen Code zuvor Code getestet und es hatte kein Feldtrennzeichen als "," so bearbeitet es jetzt.

EDIT3: Erklärung von oben.

awk -F, -vs1="\"" 'NR>1{         ##### Setting Field separator as comma(,). Creating a variable named s1 whose value is a quote("). Then Checking here if current line number is greater than 1. 
                  ##### If above condition is TRUE then all following statements will be executing. 
       gsub(/\"/,"",$8);       ##### substituting all quotes(") in $8 now. 
     if($8==1){         ##### Check if 8th field value is 1, if yes then it will execute following statement. 
       sub(/.*/,s1 "success" s1,$8)  ##### substitute everything in $8 with s1 "success" s1 
       }; 
       if($8==2){         ##### Similarly like above checking if $8's value is 2 
       sub(/.*/,s1 "check" s1,$8)  ##### Then substitute the $8's value with s1 "check" s1 
       }; 
       if($8=="null"){       ##### checking if $8's value is "null" here 
       sub(/.*/,s1 "undefined" s1,$8) ##### substituting the complete value of $8 with s1 "undefined" s1. 
         }; 
     print          ##### printing the whole line now. 
     } 
    ' OFS=, Input_file         ##### Setting output field separator as a comma. Then mentioning the Input_file here. 
+0

Hallo @ RavinderSingh13 Ich werde es versuchen, danke :) – sandatomo

+0

Hallo alle (MODs), jemand hat mir eine -ve Abstimmung über diese Lösung gegeben. Ich möchte die Person bitten, den Grund dafür anzugeben. Damit ich meine Antwort verbessern oder im Falle von Fehlern/Problemen darin bearbeiten kann. – RavinderSingh13

+0

@ RavinderSingh13 .. Von einem anonymen Passanten wurde mir ein ebenso hilfreicher Downvote gewährt. Diese Dinge passieren von Zeit zu Zeit. Beschuldige die Trolle. – ghoti

0

Sie könnten so etwas wie dies versuchen:

awk 'BEGIN {OFS=FS=",";r["\"\""] = "\"undefined\""; r["\"1\""]= "\"success\""; r["\"2\""]="\"check\""} {if($8 in r) $8 = r[$8]} 1' input_file 

Erklärung

  • die BEGIN Teile setzt einen Ersatz-Mapping in r auf. z.B. r["\"1\""]= "\"success\""; ist eine Karte des literalen Tokens "1" (a 1 mit den qoutes!) Zum literalen Wert "success" (auch einschließlich der Anführungszeichen!)
  • zusätzlich FS und OFS gesetzt Komma als Eingangs- und Ausgangstrennzeichen im BEGIN Teil
  • der Teil nach der Definition von r besteht aus einem Test zu verwenden, wenn der Wert des Feldes $8 ein Schlüssel in der Karte ist, wenn ja, dann wird das Feld $8 durch den in der Karte r für diesen Schlüssel
  • definierten Wert ersetzt. Die Frage ist nicht 100% klar, wenn in der Spalte $8 nicht zugeordnete Werte vorhanden sind. Verwenden Sie diese daher als Ausgangspunkt für Ihre eigenen Experimente
+0

wahrscheinlich am besten zu qualifizieren Ersatz mit '$ 8 in r 'andernfalls wird nicht übereinstimmende Felder entfernen. – karakfa

+0

@LarsFischer danke für Ihre Hilfe, ich weiß nicht warum, aber mit den Nullfeldern hat es nicht funktioniert, vielleicht ist es wegen awk Implementierung, ich verwende eine HP-UX Unix-Maschine, Grüße – sandatomo

+0

Lars, wenn Sie nicht Wenn Sie 'OFS' nicht setzen, werden in der Ausgabe Felder durch Leerzeichen anstelle von Kommas getrennt. Es wäre auch großartig, wenn Sie erklären könnten, was Ihre Lösung eigentlich * tut *, damit das OP leichter von Ihrer Antwort lernen kann. – ghoti

Verwandte Themen