J'ai un problème simple auquel je n'arrive pas à trouver une solution appropriée. J'ai une ligne avec de nombreuses lignes comme celle-ci:
cat test.csv | awk -F ';' '{print $1,$2,$3,$4,$5,$6}' | awk '{if($3 == 954) print "1;"$0;}'
Je veux ajouter un préfixe 1;
à toutes les lignes où le 3ème champ correspond à 954 , donc ça finit comme ça:
1;2020-10-07;2020-07-17;954;7004;something;something 2020-10-14;2020-07-16;955;10038;something;something
J'ai une très mauvaise façon de faire ça maintenant avec:
2020-10-07;2020-07-17;954;7004;something;something 2020-10-14;2020-07-16;955;10038;something;something
3 Réponses :
Awk peut faire votre travail facilement
awk 'BEGIN{ FS=OFS=";" # set input and output field separator } $3 == 954{ # if 3rd field equal to 954 then print 1,$0; # print 1 and then existing record/row next # go to next line }1 '
Avec vos fichiers d'entrée:
$ cat file 2020-10-07;2020-07-17;954;7004;something;something 2020-10-14;2020-07-16;955;10038;something;something $ awk 'BEGIN{FS=OFS=";"}$3 == 954{print 1,$0;next}1' file 1;2020-10-07;2020-07-17;954;7004;something;something 2020-10-14;2020-07-16;955;10038;something;something $ awk 'BEGIN{FS=OFS=";"}$3 == 954{$0=1 OFS $0}1' file 1;2020-10-07;2020-07-17;954;7004;something;something 2020-10-14;2020-07-16;955;10038;something;something $ awk 'BEGIN{FS=OFS=";"}{print ($3==954 ? 1 OFS:"") $0}' file 1;2020-10-07;2020-07-17;954;7004;something;something 2020-10-14;2020-07-16;955;10038;something;something
Explication
awk 'BEGIN{FS=OFS=";"}$3 == 954{print 1,$0;next}1' file #OR awk 'BEGIN{FS=OFS=";"}$3 == 954{$0=1 OFS $0}1' file #OR awk 'BEGIN{FS=OFS=";"}{print ($3==954 ? 1 OFS:"") $0}' file
$ 3 == 954 {$ 0 = 1 OFS $ 0} 1
: si le 3ème champ est égal à 954, modifiez l'enregistrement / la ligne existante ( $ 0
), avec value 1
, séparateur de champ de sortie OFS
puis ligne / enregistrement existant ( $ 0
).
Donc à la fin } 1
: Le 1 à la fin de votre script est une condition (toujours vraie) sans action, donc il exécute l'action par défaut pour chaque ligne, imprimant la ligne (qui peut avoir été modifiée par l'action précédente entre accolades)
Merci beaucoup, cela a parfaitement fonctionné pour moi et j'apprécie vraiment l'explication! :)
Heureux de savoir que cela a aidé. Vous pouvez accepter la réponse si vous pensez qu'elle est résolue
Ce one-liner peut également aider:
awk -F';' '{p=$3==954?"1;":""}{print p$0}' file
La raison pour laquelle vous avez perdu le ;
dans la sortie:
Si vous écrivez print $ 1, $ 2 ...
awk utilisera le OFS
par défaut qui est un espace. Pour résoudre le problème, vous avez essentiellement deux façons de procéder:
OFS
c'est simple, comme le montre l'autre réponse $ 2 = ...
, utilisez plutôt sub ()
, gsub ()
pour changer le texte. Lorsque vous imprimez, n'incluez pas de virgule ,
, imprimez simplement $ 0
en concaténant d'autres chaînes. (mon one-liners montre de cette façon) Avec sed
, macthing la 3ème colonne devrait être bien, mais s'il y a plus de 5 colonnes, alors awk
est le chemin.
sed '/\([^;]*\)\([^;]*\);954[^;]*\(.*\)/s/^/1;/' file.txt