web-dev-qa-db-fra.com

Conversion d'une chaîne multiligne en une seule ligne séparée par des virgules

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?

71
Alex Coplan

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 fichier
  • sed élimine simplement le , final et le transforme en une nouvelle ligne (si vous ne voulez pas de nouvelle ligne, vous pouvez faire s/,$//
70
Dan Fego

Propre et simple:

awk '{print $2}' file.txt | paste -s -d, -
119
Mattias Ahnberg
$ 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
9
kev

Cela devrait fonctionner aussi

awk '{print $2}' file | sed ':a;{N;s/\n/,/};ba'
8
jaypal singh
cat data.txt | xargs | sed -e 's/ /, /g'
7
Bhargav Srinivasan

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
6
potong

awk une doublure

$ awk '{printf (NR>1?",":"") $2}' file

+12.0,+15.5,+9.0,+13.5
4
batMan

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 .

3
Aquarius Power

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.

2
kenorb

Vous n'avez pas vu cette solution simple avec awk

awk 'b{b=b","}{b=b$2}END{print b}' infile
2
ctac_

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

1
Quatro por Quatro

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
0
fge

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.

0
elias

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.

0
Chris Koknat

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
0
Marki

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
0
user982733