Mám několik souborů, každý s jiným počtem sloupců. Chci je převést a vložit je do databáze.
Například soubor 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
Můj požadovaný výstup je:
("0001","000000000000001","john smith","45","500"), ("0002","000000000000002","peter jackson","20","80"), ("0003","000000000000002","robert brown","35","100"), ("0004","000000000000007","sarah white","40","300");
k dosažení tohoto cíle používám následující skript:
cat test01 |awk -F"\t" "{print "("\"""$1""\"","\"""$2""\"","\"""$3""\"","\"""$4""\"","\"""$5""\""),"}" |sed "$ s/.$/;/"
A funguje to dobře, problém je, když najdu jiný soubor s jiným počtem sloupců, takže musím skript upravit ručně.
Vím, že mohu získat počet sloupců s proměnnou NF AWK, ale jak kombinovat tuto proměnnou se smyčkou for ve skriptu?
Když to zkusím
cat test01 | awk "{for (i = 1; i <= NF; i++){print $i""\"","\"""}}"
dostanu tento výsledek:
0001"," 000000000000001"," john"," smith"," 45"," 500"," 0002"," 000000000000002"," peter"," jackson"," 20"," 80"," 0003"," 000000000000002"," robert"," brown"," 35"," 100"," 0004"," 000000000000007"," sarah"," white"," 40"," 300","
Komentáře
- Existuje v původním souboru oddělovač karet, nebo je to jen " nějaké mezery "?
- Jedná se o oddělovač karet
Odpověď
Používání 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");
skript má čtyři části:
-
s/^/("/
nahradí začátek řádku("
. -
s/\t/","/g
nahradí karty za","
. Toto je bit, který vyžaduje GNUsed
. U ostatníchsed
implementací vložte místo\t
doslovnou tabulátor. -
s/$/"),/
nahradí konec řádku znakem"),
. -
$s/.$/;/
nahradí čárku na konci poslední řádek (pouze) s;
.
Komentáře
- Spustím skript a vybízí " > " tak, jak něco očekává
- @ user3333911 Měl jsem neodpovídající citace, ze starší verze. Opraveno a otestováno.
Odpovědět
Pokud je váš vstupní soubor oddělen od karet, můžete zkusit následující:
awk -F"\t" -vq=""" -vOFS="","" "$1=$1 {print "(" q $0 q ");"}" filename
Nebo vložte uvozovky do funkce tisku:
awk -F"\t" -vOFS="","" "$1=$1 {print "(" "\x27" $0 "\x27" ");"}" filename
Komentáře
- Sledujte čárky na konci všech řádků kromě posledního …
- Všimněte si, že @Kusalananda. Udělal jsem rychlou opravu jako v
awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'
. Nějaký lepší návrh? - Ne, tato ' je dobrá oprava.
Odpověď
K dosažení stejného chování, jaké chcete u počátečního skriptu, můžete použít metodu awk „printf“. Umožňuje zbavit se nových řádků, které jsou vloženy pomocí „tisku“. Myslím, že váš skript by měl být přepsán takto:
cat test01 | awk "{for (i = 1; i <= NF; i++){printf $i""\"","\"""}; printf "\n";}"