boucle bash à travers la liste des chaînes


13

Est-il possible de formater cet exemple:

for i in string1 string2 stringN
do
 echo $i
done

à quelque chose de similaire à ceci:

for i in 
string1
string2
stringN
do
 echo $i
done

EDIT: Désolé pour la confusion, je ne savais pas qu'il y avait différentes méthodes d'exécution de script - sh <scriptname>versus bash <scriptname>et aussi cette chose que je ne peux pas nommer pour le moment - #!/bin/shet #!/bin/bash:)


Quel est le problème que vous essayez de résoudre?
jesse_b

Avez-vous essayé ce que vous demandez pour voir si cela fonctionnerait?
DopeGhoti

@Jesse_b lisibilité et maniabilité d'un tas de chaînes

@DopeGhoti oui je l'ai fait

@waayee: Dans ce cas, un tableau est votre meilleur choix. Voir la réponse de Glenn Jackman.
jesse_b

Réponses:


32

L'utilisation de tableaux dans bash peut faciliter la lisibilité: cette syntaxe de tableau permet des espaces arbitraires entre les mots.

strings=(
    string1
    string2
    "string with spaces"
    stringN
)
for i in "${strings[@]}"; do
    echo "$i"
done

1
Cela semble plus élégant, mais donne malheureusement une erreur: Erreur de syntaxe: "(" inattendu

1
@waayee, alors vous ne l'exécutez pas dans Bash. N'oubliez pas que ce shn'est pas nécessairement Bash, et surtout pas sur Debian et Ubuntu.
ilkkachu

1
@ilkkachu Je pense que je comprends maintenant - doit exécuter "bash <scriptname>" et non "sh <scriptname>" :)

@waayee, ou mettez une ligne hashbang / shebang appropriée et exécutez-la comme un exécutable. Lecture obligatoire: le shebang détermine-t-il le shell qui exécute le script?
ilkkachu

1
@rrrrr, vos questions sont probablement répondues ici: stackoverflow.com/q/12314451/7552
glenn jackman

4

Vous pouvez échapper au saut de ligne avec une barre oblique inverse:

$ for i in \
> hello \
> world
> do
> echo $i
> done
hello
world
$

2

Vous pouvez échapper aux sauts de ligne avant / après chaque élément que vous parcourez:

for i in \
    string1 \
    string2 \
    stringN
do
   printf '%s\n' "$i"
done

Ou, pour cet exemple simple:

printf '%s\n' string1 string2 stringN

qui a le même résultat.

En relation:

Variation à l'aide d'un bashtableau:

strings=(
    string1
    string2
    stringN
)

printf '%s\n' "${strings[@]}"

1

Si le passage à zshest une option:

for string (
  string1
  'other string'
  etc..
) printf '%s\n' "$string"

0

Vous pouvez utiliser la loopcommande, disponible ici , comme ceci:

$ loop "echo $ITEM" --for string1,string2,string3

ou, si vous avez une liste sous forme de fichier:

$ cat file_list.txt | loop "echo $ITEM"

0
list='a b c d'
for element in $list;do 
    echo "$element"
done

Il vous manque des points-virgules!
41754

Notez que cela fonctionnerait tant que chaque chaîne est un mot distinct. Dès que vous avez des espaces dans vos chaînes, les espaces séparent la chaîne en plusieurs mots. De plus, si la $listchaîne contient des caractères de list='* * * *'remplacement de nom de fichier ( ), le shell pourrait potentiellement les remplacer par des noms de fichiers correspondants.
Kusalananda

0

Même chose, moins de texte:

array=(
        string{1..7}
)

for i in "${array[@]}"; do
    echo "$i"
done

string1etc. ne sont pas les valeurs littérales à afficher, ce sont des espaces réservés, donc cette approche ne fonctionne pas.
Stephen Kitt

si oui, pourquoi s'embêter array ( … )? fais juste for i in string{1..7}; do echo "$i"; done; pairprintf '%s\n' string{1..7}
αғsнιη
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.