Disons que j'ai la chaîne suivante:
something1: +12.0 (some unnecessary trailing data (this must go))
something2: +15.5 (some more unnecessary trailing data)
something4: +9.0 (some other unnecessary data)
something1: +13.5 (blah blah blah)
Comment puis-je transformer cela en tout simplement
+12.0,+15.5,+9.0,+13.5
en bash?
Vous pouvez utiliser awk
et sed
:
awk -vORS=, '{ print $2 }' file.txt | sed 's/,$/\n/'
Ou si vous voulez utiliser un tuyau:
echo "data" | awk -vORS=, '{ print $2 }' | sed 's/,$/\n/'
Pour le décomposer:
awk
est idéal pour gérer les données décomposées en champs-vORS=,
définit le "séparateur d'enregistrement de sortie" sur ,
, ce que vous vouliez{ print $2 }
indique à awk
d'imprimer le deuxième champ pour chaque enregistrement (ligne)file.txt
est votre nom de fichiersed
élimine simplement le ,
final et le transforme en une nouvelle ligne (si vous ne voulez pas de nouvelle ligne, vous pouvez faire s/,$//
Propre et simple:
awk '{print $2}' file.txt | paste -s -d, -
$ awk -v ORS=, '{print $2}' data.txt | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5
$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5
Cela devrait fonctionner aussi
awk '{print $2}' file | sed ':a;{N;s/\n/,/};ba'
cat data.txt | xargs | sed -e 's/ /, /g'
Cela pourrait fonctionner pour vous:
cut -d' ' -f5 file | paste -d',' -s
+12.0,+15.5,+9.0,+13.5
ou
sed '/^.*\(+[^ ]*\).*/{s//\1/;H};${x;s/\n/,/g;s/.//p};d' file
+12.0,+15.5,+9.0,+13.5
awk une doublure
$ awk '{printf (NR>1?",":"") $2}' file
+12.0,+15.5,+9.0,+13.5
essaye ça:
sedSelectNumbers='s".* \(+[0-9]*[.][0-9]*\) .*"\1,"'
sedClearLastComma='s"\(.*\),$"\1"'
cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma"
la bonne chose est la partie facile de la suppression des caractères "\ n" de nouvelle ligne!
EDIT: un autre excellent moyen de joindre des lignes en une seule ligne avec sed est le suivant: |sed ':a;N;$!ba;s/\n/ /g'
obtenu de ici .
Vous pouvez utiliser grep
:
grep -o "+\S\+" in.txt | tr '\n' ','
qui trouve la chaîne commençant par +
, suivi de toute chaîne \S\+
, puis convertit les nouveaux caractères de ligne en virgules. Cela devrait être assez rapide pour les gros fichiers.
Vous n'avez pas vu cette solution simple avec awk
awk 'b{b=b","}{b=b$2}END{print b}' infile
Une solution écrite en pur Bash:
#!/bin/bash
sometext="something1: +12.0 (some unnecessary trailing data (this must go))
something2: +15.5 (some more unnecessary trailing data)
something4: +9.0 (some other unnecessary data)
something1: +13.5 (blah blah blah)"
a=()
while read -r a1 a2 a3; do
# we can add some code here to check valid values or modify them
a+=("${a2}")
done <<< "${sometext}"
# between parenthesis to modify IFS for the current statement only
(IFS=',' ; printf '%s: %s\n' "Result" "${a[*]}")
Résultat: + 12,0, + 15,5, + 9,0, + 13,5
Avec Perl:
fg@erwin ~ $ Perl -ne 'Push @l, (split(/\s+/))[1]; END { print join(",", @l) . "\n" }' <<EOF
something1: +12.0 (some unnecessary trailing data (this must go))
something2: +15.5 (some more unnecessary trailing data)
something4: +9.0 (some other unnecessary data)
something1: +13.5 (blah blah blah)
EOF
+12.0,+15.5,+9.0,+13.5
Vous pouvez également le faire avec deux appels sed:
$ cat file.txt
something1: +12.0 (some unnecessary trailing data (this must go))
something2: +15.5 (some more unnecessary trailing data)
something4: +9.0 (some other unnecessary data)
something1: +13.5 (blah blah blah)
$ sed 's/^[^:]*: *\([+0-9.]\+\) .*/\1/' file.txt | sed -e :a -e '$!N; s/\n/,/; ta'
+12.0,+15.5,+9.0,+13.5
Le premier appel sed supprime les données sans intérêt et le second joint toutes les lignes.
Une autre solution Perl, similaire au awk de Dan Fego:
Perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'
-a
indique à Perl de scinder la ligne d'entrée dans le tableau @F, qui est indexé à partir de 0.
Eh bien, le plus difficile est probablement de choisir la deuxième "colonne", car je ne saurais pas comment traiter plusieurs espaces en un. Pour le reste c'est facile. Utilisez des substitutions bash.
# cat bla.txt
something1: +12.0 (some unnecessary trailing data (this must go))
something2: +15.5 (some more unnecessary trailing data)
something4: +9.0 (some other unnecessary data)
something1: +13.5 (blah blah blah)
# cat bla.sh
OLDIFS=$IFS
IFS=$'\n'
for i in $(cat bla.txt); do
i=$(echo "$i" | awk '{print $2}')
u="${u:+$u, }$i"
done
IFS=$OLDIFS
echo "$u"
# bash ./bla.sh
+12.0, +15.5, +9.0, +13.5
Vous pouvez aussi imprimer comme ceci:
Just awk: using printf
bash-3.2$ cat sample.log
something1: +12.0 (some unnecessary trailing data (this must go))
something2: +15.5 (some more unnecessary trailing data)
something4: +9.0 (some other unnecessary data)
something1: +13.5 (blah blah blah)
bash-3.2$ awk ' { if($2 != "") { if(NR==1) { printf $2 } else { printf "," $2 } } }' sample.log
+12.0,+15.5,+9.0,+13.5