Jai plusieurs fichiers, chacun avec un nombre de colonnes différent. Je veux les convertir pour les insérer dans une base de données
Par exemple le fichier 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
Ma sortie souhaitée est:
("0001","000000000000001","john smith","45","500"), ("0002","000000000000002","peter jackson","20","80"), ("0003","000000000000002","robert brown","35","100"), ("0004","000000000000007","sarah white","40","300");
pour y parvenir, jutilise le script suivant:
cat test01 |awk -F"\t" "{print "("\"""$1""\"","\"""$2""\"","\"""$3""\"","\"""$4""\"","\"""$5""\""),"}" |sed "$ s/.$/;/"
Et cela fonctionne bien, le problème est quand je trouve un autre fichier avec un nombre de colonnes différent, donc je dois modifier le script manuellement.
Je sais que je peux obtenir le nombre de colonnes avec la variable NF de lAWK, mais comment combiner cette variable avec une boucle for dans le script?
Quand jessaye
cat test01 | awk "{for (i = 1; i <= NF; i++){print $i""\"","\"""}}"
Jobtiens ce résultat:
0001"," 000000000000001"," john"," smith"," 45"," 500"," 0002"," 000000000000002"," peter"," jackson"," 20"," 80"," 0003"," 000000000000002"," robert"," brown"," 35"," 100"," 0004"," 000000000000007"," sarah"," white"," 40"," 300","
Commentaires
- Dans le fichier dorigine, y a-t-il un délimiteur de tabulation ou est-ce simplement " des espaces "?
- Cest un délimiteur donglet
Réponse
Utilisation de 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");
Le est en quatre parties:
-
s/^/("/
remplace le début de la ligne par("
. -
s/\t/","/g
remplace les onglets par","
. Cest le bit qui nécessite GNUsed
. Pour les autres implémentations desed
, insérez une tabulation littérale à la place de\t
. -
s/$/"),/
remplace la fin de la ligne par"),
. -
$s/.$/;/
remplace la virgule à la fin du dernière ligne (uniquement) avec;
.
Commentaires
- Je lance le script et il invite " > " en attente de quelque chose
- @ user3333911 Javais des citations incohérentes, dune version antérieure. Corrigé maintenant et testé.
Réponse
Si votre fichier dentrée est séparé par des tabulations, vous pouvez essayer ce qui suit:
awk -F"\t" -vq=""" -vOFS="","" "$1=$1 {print "(" q $0 q ");"}" filename
Ou incorporer des guillemets dans la fonction dimpression:
awk -F"\t" -vOFS="","" "$1=$1 {print "(" "\x27" $0 "\x27" ");"}" filename
Commentaires
- Regardez les virgules à la fin de toutes les lignes sauf pour la dernière …
- Bonne remarque @Kusalananda. Jai fait une solution rapide comme dans
awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q "),"}' filename | sed '$s/,$/;/'
. Une meilleure suggestion? - Non, cette ' est une bonne solution.
Réponse
Pour atteindre le même comportement que vous le souhaitez avec votre script initial, vous pouvez utiliser la méthode « printf » de awk. Il permet de se débarrasser des retours à la ligne qui sont mis par « print ». Je suppose que votre script devrait être réécrit comme ceci:
cat test01 | awk "{for (i = 1; i <= NF; i++){printf $i""\"","\"""}; printf "\n";}"