Ho diversi file, ognuno con un diverso numero di colonne. Voglio convertirli per inserirli in un database
Ad esempio il file 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
Il mio output desiderato è:
("0001","000000000000001","john smith","45","500"), ("0002","000000000000002","peter jackson","20","80"), ("0003","000000000000002","robert brown","35","100"), ("0004","000000000000007","sarah white","40","300");
per ottenere ciò utilizzo il seguente script:
cat test01 |awk -F"\t" "{print "("\"""$1""\"","\"""$2""\"","\"""$3""\"","\"""$4""\"","\"""$5""\""),"}" |sed "$ s/.$/;/"
E funziona bene, il problema è quando trovo un altro file con un numero diverso di colonne, quindi devo modificare lo script manualmente.
So di poter ottenere il numero di colonne con la variabile NF di AWK, ma come combinare questa variabile con un ciclo for nello script?
Quando provo
cat test01 | awk "{for (i = 1; i <= NF; i++){print $i""\"","\"""}}"
ottengo questo risultato:
0001"," 000000000000001"," john"," smith"," 45"," 500"," 0002"," 000000000000002"," peter"," jackson"," 20"," 80"," 0003"," 000000000000002"," robert"," brown"," 35"," 100"," 0004"," 000000000000007"," sarah"," white"," 40"," 300","
Commenti
- Nel file originale è presente un delimitatore di tabulazione o è solo " alcuni spazi "?
- È un delimitatore di tabulazione
Risposta
Utilizzo di 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");
Il lo script è composto da quattro parti:
-
s/^/("/
sostituisce linizio della riga con("
. -
s/\t/","/g
sostituisce le tabulazioni con","
. Questo è il bit che richiede GNUsed
. Per altresed
implementazioni, inserisci una tabulazione letterale al posto di\t
. -
s/$/"),/
sostituisce la fine della riga con"),
. -
$s/.$/;/
sostituisce la virgola alla fine del ultima riga (solo) con;
.
Commenti
- Eseguo lo script e richiede " > " in attesa di qualcosa
- @ user3333911 Avevo virgolette non corrispondenti, da una versione precedente. Risolto ora e testato.
Risposta
Se il file di input è separato da tabulazioni, puoi provare quanto segue:
awk -F"\t" -vq=""" -vOFS="","" "$1=$1 {print "(" q $0 q ");"}" filename
Oppure incorpora virgolette nella funzione di stampa:
awk -F"\t" -vOFS="","" "$1=$1 {print "(" "\x27" $0 "\x27" ");"}" filename
Commenti
- Guarda le virgole alla fine di tutte le righe tranne lultima …
- Buona comunicazione @Kusalananda. Ho eseguito una soluzione rapida come in
awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'
. Qualche suggerimento migliore? - No, ' è una buona soluzione.
Risposta
Per ottenere lo stesso comportamento che desideri con lo script iniziale puoi utilizzare il metodo “printf” di awk. Rende possibile sbarazzarsi di newline che sono messi da “print”. Immagino che il tuo script dovrebbe essere riscritto in questo modo:
cat test01 | awk "{for (i = 1; i <= NF; i++){printf $i""\"","\"""}; printf "\n";}"