So optimieren Sie ein Skript mit NF und einer for-Schleife

Ich habe mehrere Dateien mit jeweils unterschiedlicher Spaltenanzahl. Ich möchte sie konvertieren, um sie in eine Datenbank einzufügen.

Zum Beispiel die Datei test01:

0001 000000000000001 john smith 45 500 0002 000000000000002 peter jackson 20 80 0003 000000000000002 robert brown 35 100 0004 000000000000007 sarah white 40 300 

Meine gewünschte Ausgabe lautet:

("0001","000000000000001","john smith","45","500"), ("0002","000000000000002","peter jackson","20","80"), ("0003","000000000000002","robert brown","35","100"), ("0004","000000000000007","sarah white","40","300"); 

Um dies zu erreichen, verwende ich das folgende Skript:

cat test01 |awk -F"\t" "{print "("\"""$1""\"","\"""$2""\"","\"""$3""\"","\"""$4""\"","\"""$5""\""),"}" |sed "$ s/.$/;/" 

Und es funktioniert gut, Das Problem ist, wenn ich eine andere Datei mit einer anderen Anzahl von Spalten finde, daher muss ich das Skript manuell ändern.

Ich weiß, dass ich die Anzahl der Spalten mit der Variablen NF des AWK erhalten kann, aber wie Um diese Variable mit einer for-Schleife im Skript zu kombinieren?

Wenn ich versuche

cat test01 | awk "{for (i = 1; i <= NF; i++){print $i""\"","\"""}}" 

, erhalte ich folgendes Ergebnis:

0001"," 000000000000001"," john"," smith"," 45"," 500"," 0002"," 000000000000002"," peter"," jackson"," 20"," 80"," 0003"," 000000000000002"," robert"," brown"," 35"," 100"," 0004"," 000000000000007"," sarah"," white"," 40"," 300"," 

Kommentare

  • Gibt es in der Originaldatei ein Tabulatortrennzeichen oder nur " einige Leerzeichen "?
  • Es ist ein Tabulatortrennzeichen

Antwort

Verwenden von GNU sed:

$ sed -e "s/^/("/" -e "s/\t/","/g" -e "s/$/"),/" -e "$s/.$/;/" file ("0001","000000000000001","john smith","45","500"), ("0002","000000000000002","peter jackson","20","80"), ("0003","000000000000002","robert brown","35","100"), ("0004","000000000000007","sarah white","40","300"); 

Die -Skript besteht aus vier Teilen:

  1. s/^/("/ ersetzt den Zeilenanfang durch (".
  2. s/\t/","/g ersetzt Registerkarten durch ",". Dies ist das Bit, für das GNU sed erforderlich ist. Fügen Sie für andere sed -Implementierungen anstelle von \t eine Literal-Registerkarte ein.
  3. s/$/"),/ ersetzt das Zeilenende durch "),.
  4. $s/.$/;/ ersetzt das Komma am Ende von letzte Zeile (nur) mit ;.

Kommentare

  • Ich führe das Skript aus und es fordert " > " auf, etwas zu erwarten
  • @ user3333911 Ich hatte nicht übereinstimmende Anführungszeichen aus einer früheren Version. Jetzt behoben und getestet.

Antwort

Wenn Ihre Eingabedatei durch Tabulatoren getrennt ist, können Sie Folgendes versuchen:

awk -F"\t" -vq=""" -vOFS="","" "$1=$1 {print "(" q $0 q ");"}" filename 

Oder binden Sie Anführungszeichen in die Druckfunktion ein:

awk -F"\t" -vOFS="","" "$1=$1 {print "(" "\x27" $0 "\x27" ");"}" filename 

Kommentare

  • Beachten Sie die Kommas am Ende aller Zeilen mit Ausnahme der letzten …
  • Gute Nachricht dort @Kusalananda. Ich habe eine schnelle Lösung wie in awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/' durchgeführt. Gibt es einen besseren Vorschlag?
  • Nein, ' ist eine gute Lösung.

Antwort

Um mit Ihrem ursprünglichen Skript das gleiche Verhalten wie zu erreichen, können Sie die „printf“ -Methode von awk verwenden. Es ermöglicht die Beseitigung von Zeilenumbrüchen, die durch „Drucken“ gesetzt werden. Ich vermute, Ihr Skript sollte folgendermaßen umgeschrieben werden:

cat test01 | awk "{for (i = 1; i <= NF; i++){printf $i""\"","\"""}; printf "\n";}" 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.