Cum se optimizează scriptul cu NF și o buclă for

Am mai multe fișiere, fiecare cu număr diferit de coloane. Vreau să le convertesc pentru a le insera într-o bază de date

De exemplu, fișierul 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 

Rezultatul meu dorit este:

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

pentru a realiza acest lucru, folosesc următorul script:

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

Și funcționează bine, problema este când găsesc un alt fișier cu un număr diferit de coloane, așa că trebuie să modific manual scriptul.

Știu că pot obține numărul de coloane cu variabila NF a AWK, dar cum pentru a combina această variabilă cu o buclă for din script?

Când încerc

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

obțin acest rezultat:

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

Comentarii

  • În fișierul original, există un delimitator de file sau este doar " unele spații albe "?
  • Este un delimitator de file

Răspuns

Utilizarea 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"); 

scriptul este format din patru părți:

  1. s/^/("/ înlocuiește începutul liniei cu (".
  2. s/\t/","/g înlocuiește filele cu ",". Acesta este bitul care necesită GNU sed. Pentru alte sed implementări, introduceți o filă literală în locul \t.
  3. s/$/"),/ înlocuiește sfârșitul liniei cu "),.
  4. $s/.$/;/ înlocuiește virgula la sfârșitul ultima linie (numai) cu ;.

Comentarii

  • Execut scriptul și solicită " > " așteaptă ceva
  • @ user3333911 Am avut citate necorespunzătoare, dintr-o versiune anterioară. Remediat acum și testat.

Răspuns

Dacă fișierul de intrare este separat de tab, puteți încerca următoarele:

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

Sau încorporați ghilimele în funcția de imprimare:

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

Comentarii

  • Urmăriți virgulele la sfârșitul tuturor rândurilor, cu excepția ultimului …
  • Bună notă acolo @Kusalananda. Am făcut o soluție rapidă ca în awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'. Aveți vreo sugestie mai bună?
  • Nu, ' este o soluție bună.

Răspuns

Pentru a atinge același comportament pe care îl doriți cu scriptul inițial, puteți utiliza metoda „printf” de awk. Face posibilă scăparea de linii noi care sunt puse prin „tipărire”. Cred că scriptul dvs. ar trebui rescris astfel:

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

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *