web-dev-qa-db-fra.com

Comment scinder une liste par virgule et non par espace

Je veux diviser un texte avec une virgule , sans espace dans for foo in list. Supposons que j'ai un fichier CSV CSV_File avec le texte suivant à l'intérieur:

Hello,World,Questions,Answers,bash Shell,script
...

J'ai utilisé le code suivant pour le scinder en plusieurs mots:

for Word in $(cat CSV_File | sed -n 1'p' | tr ',' '\n')
do echo $Word
done

Il imprime:

Hello
World
Questions
Answers
bash
Shell
script

Mais je veux que le texte soit divisé par des virgules et non des espaces:

Hello
World
Questions
Answers
bash Shell
script

Comment puis-je y arriver en bash?

41
Eng.Fouad

Utiliser une substitution de sous-coque pour analyser les mots annule tout le travail que vous faites pour mettre des espaces ensemble.

Essayez plutôt:

cat CSV_file | sed -n 1'p' | tr ',' '\n' | while read Word; do
    echo $Word
done

Cela augmente également le parallélisme. L'utilisation d'un sous-shell comme dans votre question oblige l'ensemble du processus de sous-shell à se terminer avant de pouvoir commencer à parcourir les réponses. Piping vers un sous-shell (comme dans ma réponse) leur permet de travailler en parallèle. Cela n'a d'importance que si vous avez beaucoup de lignes dans le fichier, bien sûr.

44
mkj

Définissez IFS à,:

sorin@sorin:~$ IFS=',' ;for i in `echo "Hello,World,Questions,Answers,bash Shell,script"`; do echo $i; done
Hello
World
Questions
Answers
bash Shell
script
sorin@sorin:~$ 
47
Sorin

Je pense que la méthode canonique est:

while IFS=, read field1 field2 field3 field4 field5 field6; do 
  do stuff
done < CSV.file

Si vous ne savez pas ou ne vous souciez pas du nombre de champs:

IFS=,
while read line; do
  # split into an array
  field=( $line )
  for Word in "${field[@]}"; do echo "$Word"; done

  # or use the positional parameters
  set -- $line
  for Word in "$@"; do echo "$Word"; done

done < CSV.file
17
glenn jackman
kent$  echo "Hello,World,Questions,Answers,bash Shell,script"|awk -F, '{for (i=1;i<=NF;i++)print $i}'
Hello
World
Questions
Answers
bash Shell
script
8
Kent

Créer une fonction bash

split_on_commas() {
  local IFS=,
  local Word_LIST=($1)
  for Word in "${Word_LIST[@]}"; do
    echo "$Word"
  done
}

split_on_commas "this,is a,list" | while read item; do
  # Custom logic goes here
  echo Item: ${item}
done

... cela génère la sortie suivante:

Item: this
Item: is a
Item: list

(Remarque, cette réponse a été mise à jour en fonction de certains commentaires.)

7

Lire: http://linuxmanpages.com/man1/sh.1.php & http://www.gnu.org/s/hello/manual/autoconf/Special-Shell-Variables .html

IFS Séparateur de champ interne utilisé pour le fractionnement de Word après expansion et pour fractionner les lignes en mots avec le lu commande intégrée. La valeur par défaut est `` ''.

IFS étant une variable d’environnement Shell, il restera inchangé dans le contexte de votre script Shell, mais pas autrement, à moins que vous ne l’exportiez. Sachez également que l’IFS ne sera probablement pas hérité de votre environnement: consultez le présent message général pour les raisons et plus d’informations sur l’IFS. 

Votre code est écrit comme ceci:

IFS=","
for Word in $(cat tmptest | sed -n 1'p' | tr ',' '\n'); do echo $Word; done;

devrait fonctionner, je l’ai testé en ligne de commande.

sh-3.2#IFS=","
sh-3.2#for Word in $(cat tmptest | sed -n 1'p' | tr ',' '\n'); do echo $Word; done;
World
Questions
Answers
bash Shell
script
5
Ashley Raiteri

Vous pouvez utiliser:

cat f.csv | sed 's/,/ /g' |  awk '{print $1 " / " $4}'

ou

echo "Hello,World,Questions,Answers,bash Shell,script" | sed 's/,/ /g' |  awk '{print $1 " / " $4}'

C'est la partie qui remplace la virgule par l'espace

sed 's/,/ /g'
0
ozma