Hoe het script te optimaliseren met NF en een for-lus

Ik heb verschillende bestanden, elk met een ander aantal kolommen. Ik wil ze converteren om ze in een database in te voegen.

Bijvoorbeeld het bestand 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 

Mijn gewenste output is:

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

om dit te bereiken gebruik ik het volgende script:

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

En het werkt prima, het probleem is wanneer ik een ander bestand vind met een ander aantal kolommen, dus ik moet het script handmatig aanpassen.

Ik weet dat ik het aantal kolommen kan krijgen met de variabele NF van de AWK, maar hoe om deze variabele te combineren met een for-lus in het script?

Als ik het probeer

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

krijg ik dit resultaat:

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

Reacties

  • In het originele bestand staat een tabscheidingsteken, of is het gewoon " wat witruimte "?
  • Het is een tabscheidingsteken

Antwoord

GNU gebruiken 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"); 

Het script bestaat uit vier delen:

  1. s/^/("/ vervangt het begin van de regel door (".
  2. s/\t/","/g vervangt tabbladen door ",". Dit is het bit waarvoor GNU sed nodig is. Voeg voor andere sed implementaties een letterlijke tab in in plaats van \t.
  3. s/$/"),/ vervangt einde van de regel door "),.
  4. $s/.$/;/ vervangt de komma aan het einde van de laatste regel (alleen) met ;.

Reacties

  • Ik voer het script uit en het vraagt " > " als iets te verwachten
  • @ user3333911 Ik had niet-overeenkomende citaten uit een eerdere versie. Nu opgelost en getest.

Antwoord

Als uw invoerbestand door tabs gescheiden is, kunt u het volgende proberen:

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

Of sluit aanhalingstekens in de afdrukfunctie in:

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

Reacties

  • Let op de kommas aan het einde van alle regels behalve de laatste …
  • Let goed op @Kusalananda. Ik heb een snelle oplossing uitgevoerd zoals in awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'. Enige betere suggestie?
  • Nee, dat ' een goede oplossing is.

Antwoord

Om hetzelfde gedrag te bereiken als u wilt met uw eerste script, kunt u de “printf” -methode van awk gebruiken. Het maakt het mogelijk om nieuwe regels te verwijderen die door “print” zijn geplaatst. Ik vermoed dat je script als volgt moet worden herschreven:

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

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *