2017-01-05 2 views
0

Mac OS X et shell bourne:bourne shell ne casse mot inattendu

J'aime parcourir une liste d'éléments, pour lesquels certains des éléments incluant des blancs. Chaque article doit être traité dans son ensemble, mais il doit être divisé comme indiqué ci-dessous. Si je "coder en dur" comme ça, il est ok:

echo "hard coded :\n" 
for i in 'a a a' 'bcd' 'e e' 
do 
echo "$i" 
done 

Mais mettre la même chaîne dans une variable, il est faux:

echo "\nsecond loop:\n" 
# 
# str is normally coming from a comma substitution 
str="'a a a' 'bcd' 'e e'" 
echo $str 
for i in ${str} 
do 
echo "$i" 
done 

Le résultat est:

hard coded : 
a a a 
bcd 
e e 

secondes boucle:

'a a a' 'bcd' 'e e' 
'a 
a 
a' 
'bcd' 
'e 
e' 
+3

Vous utilisez 'bash', pas le shell Bourne. – chepner

+0

qu'est-ce que vous obtenez lorsque vous tapez 'echo $ SHELL'? Bonne chance. – shellter

+1

MacOS n'a pas de shell Bourne disponible.(Pour être clair, '/ bin/sh' sur les systèmes modernes est POSIX sh, ou un shell POSIX-superset tel que bash ou ksh, pas Bourne). –

Répondre

0

Utilisez un tableau:

strings=('a a a' 'bcd' 'e e') 
for i in "${strings[@]}" 
do 
echo "$i" 
done 
+0

Cette réponse utilise [bash] (https://en.wikipedia.org/wiki/Bash_ (Unix_shell)). La question porte sur [Bourne shell] (https://en.wikipedia.org/wiki/Bourne_shell), qui ne supporte pas les variables de liste. –

+1

L'utilisateur n'utilise pas Bourne shell, car Mac OS X ne vient pas avec Bourne shell. – chepner

+0

Je ne sais pas ce qui est installé sur l'ordinateur de Christian. J'ai simplement vu l'absence d'une balise bash ou de références à bash et j'ai _did_ voir une référence à "bourne shell". Je ne sais pas comment il serait difficile d'installer Almquist, Bsh ou l'un des autres sur OS X; Je suppose que ce ne serait pas difficile (bien que je ne puisse pas parler pour que les bashismes existent dans divers composants et applications du système d'exploitation). –

1

Voici un code qui définit un fichier CSV, puis itère sans avoir besoin xargs ou un autre programme externe. Ceci est POSIX entièrement portable et fonctionnera en bash ou tout /bin/sh.

#!/bin/sh 
str="a a a,*,e e" 
echo $str 
while [ "$str" != "${str#*,}" ]; do 
    echo "${str%%,*}" # just the first CSV item 
    str="${str#*,}" # remove the first CSV item 
done 
echo "$str"   # the final (or only) CSV item 

Ceci utilise la variable shell parameter expansion.


réponse originale

Vous pouvez utiliser un séparateur différent et mis $IFS (le i nput f ield de eparator) à la clé sur elle. J'utilise une virgule ici parce que vous avez sous-entendu votre entrée d'origine utilise des valeurs séparées par des virgules:

#!/bin/sh -f 

str="a a a,bcd,e e" 
echo $str 
OLDIFS="$IFS" 
IFS="," 
for i in ${str} 
do 
echo "$i" 
done 
IFS="$OLDIFS" 

Ce produit:

a a a,bcd,e e 
a a a 
bcd 
e e 

Le drapeau -f à la coquille est important de supprimer l'expansion des caractères génériques ("globbing") dans le cas d'un astérisque ou d'un caractère similaire existant dans l'entrée.

Cela fonctionne dans POSIX, Bourne, bash, korn, et la plupart des autres dans cette famille.

+0

Je m'attendrais, avec 'str =" a a, *, e e "', la sortie à contenir un littéral '*'. Un comportement qui au lieu de cela émettrait une liste de fichiers dans le répertoire courant appelle au moins un avertissement, non? –

+0

Essayez-le. Vous devriez constater que puisque la déclaration est citée, l'expansion générique est supprimée et vous obtiendrez en effet un '*' littéral. Si ce n'était pas le cas, vous auriez toutes sortes de façons d'exploiter le code. Si vous voulez réellement étendre le caractère générique, vous devrez utiliser 'eval' ... et vous devrez effectuer de nombreux tests de sécurité pour vous assurer que rien de malveillant ne se passe. –

+0

Je l'ai essayé. Je reçois une liste de répertoire. –

0

Si vous voulez chaîne de fractionnement de coquille avec des citations d'honneur, utilisez xargs:

str="'a a a' 'bcd' 'e e'" 
echo "$str" | xargs printf '%s\n' 

... émettra:

a a a 
bcd 
e e 

Cependant, en général, la bonne chose est de évitez la conception de programme qui s'attend à ce comportement.