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:
-
s/^/("/
înlocuiește începutul liniei cu("
. -
s/\t/","/g
înlocuiește filele cu","
. Acesta este bitul care necesită GNUsed
. Pentru altesed
implementări, introduceți o filă literală în locul\t
. -
s/$/"),/
înlocuiește sfârșitul liniei cu"),
. -
$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";}"