Hur man optimerar skript med NF och en för loop

Jag har flera filer, var och en med olika antal kolumner. Jag vill konvertera dem för att infoga dem i en databas

Till exempel filen 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 

Min önskade utgång är:

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

för att uppnå detta använder jag följande skript:

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

Och det fungerar bra, problemet är när jag hittar en annan fil med ett annat antal kolumner, så jag måste ändra skriptet manuellt.

Jag vet att jag kan få antalet kolumner med AWK: s variabel NF, men hur att kombinera den här variabeln med en for-loop i skriptet?

När jag försöker

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

får jag det här resultatet:

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

Kommentarer

  • I originalfilen finns det en flikavgränsare, eller är det bara " lite mellanslag "?
  • Det är en flikavgränsare

Svara

Använda 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"); 

-skriptet består av fyra delar:

  1. s/^/("/ ersätter radens början med (".
  2. s/\t/","/g ersätter flikar med ",". Detta är den bit som kräver GNU sed. För andra sed -implementeringar, sätt in en bokstavlig flik i stället för \t.
  3. s/$/"),/ ersätter radens slut med "),.
  4. $s/.$/;/ ersätter kommatecken i slutet av sista raden (endast) med ;.

Kommentarer

  • Jag kör skriptet och det uppmanas " > " som förväntat på något
  • @ user3333911 Jag hade felaktiga citat från en tidigare version. Fixat nu och testat.

Svar

Om din inmatningsfil är flikavgränsad kan du prova följande:

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

Eller bädda in citat i utskriftsfunktionen:

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

Kommentarer

  • Se kommatecken i slutet av alla rader utom den sista …
  • Bra meddelande där @Kusalananda. Jag gjorde en snabb fix som i awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'. Några bättre förslag?
  • Nej, att ' är en bra fix.

Svar

För att uppnå samma beteende som du vill med ditt ursprungliga skript kan du använda ”printf” -metoden awk. Det gör det möjligt att bli av med nya rader som sätts av ”tryck”. Jag antar att ditt skript ska skrivas om så här:

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

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *