Sådan optimeres script med NF og en for loop

Jeg har flere filer, hver med forskelligt antal kolonner. Jeg vil konvertere dem for at indsætte dem i en database

For eksempel 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 ønskede output er:

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

for at opnå dette bruger jeg følgende script:

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

Og det fungerer fint, problemet er, når jeg finder en anden fil med et andet antal kolonner, så jeg er nødt til at ændre scriptet manuelt.

Jeg ved, at jeg kan få antallet af kolonner med AWKs variabel NF, men hvordan for at kombinere denne variabel med en for-loop i scriptet?

Når jeg prøver

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

får jeg dette resultat:

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

  • Er der i originalfilen en fane, eller er det bare " noget mellemrum "?
  • Det er en tabulatorafgrænser

Svar

Brug af 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"); 

script er i fire dele:

  1. s/^/("/ erstatter start af linje med (".
  2. s/\t/","/g erstatter faner med ",". Dette er den bit, der kræver GNU sed. For andre sed implementeringer skal du indsætte en bogstavelig fane i stedet for \t.
  3. s/$/"),/ erstatter slutningen af linjen med "),.
  4. $s/.$/;/ erstatter kommaet i slutningen af sidste linje (kun) med ;.

Kommentarer

  • Jeg kører scriptet og det beder " > " som forventet til noget
  • @ user3333911 Jeg havde uoverensstemmende tilbud fra en tidligere version. Løst nu og testet.

Svar

Hvis din inputfil er faneadskilt, kan du prøve følgende:

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

Eller integrer citater i udskrivningsfunktionen:

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

Kommentarer

  • Se kommaerne i slutningen af alle linjer undtagen den sidste …
  • God opmærksomhed der @Kusalananda. Jeg lavede en hurtig løsning som i awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'. Er der et bedre forslag?
  • Nej, at ' er en god løsning.

Svar

For at nå den samme adfærd, som du vil med dit oprindelige script, kan du bruge “printf” -metoden awk. Det gør det muligt at slippe af med nye linjer, der er sat af “print”. Jeg gætter på, dit script skal omskrives sådan:

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *