GNU/Linux >> Tutoriels Linux >  >> Linux

Comment diviser une chaîne avec des guillemets (comme des arguments de commande) dans bash ?

La solution la plus simple consiste à créer un tableau des arguments entre guillemets que vous pouvez ensuite parcourir si vous le souhaitez ou passer directement à une commande.

eval "array=($string)"

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

p.s. Veuillez commenter si vous trouvez un moyen plus simple sans eval .

Modifier :

En nous appuyant sur la réponse de @Hubbitus, nous avons une version entièrement épurée et correctement citée. Remarque :c'est exagéré et laissera en fait des barres obliques inverses supplémentaires dans les sections entre guillemets doubles ou simples précédant la plupart des signes de ponctuation, mais est invulnérable aux attaques.

declare -a "array=($( echo "$string" | sed 's/[][`[email protected]#$%^&*():;<>.,?/\|{}=+-]/\\&/g' ))"

Je laisse au lecteur intéressé le soin de modifier à sa guise http://ideone.com/FUTHhj


Quand j'ai vu la réponse de David Postill, j'ai pensé "il doit y avoir une solution plus simple". Après quelques expérimentations, j'ai trouvé les œuvres suivantes :-

string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
echo $string
eval 'for word in '$string'; do echo $word; done'

Cela fonctionne car eval développe la ligne (en supprimant les guillemets et en développant string ) avant d'exécuter la ligne résultante (qui est la réponse en ligne) :

for word in "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"; do echo $word; done

Une alternative qui se développe sur la même ligne est :

eval "for word in $string; do echo \$word; done"

Ici string est développé entre guillemets, mais le $ doit être échappé pour que word n'est pas développé avant l'exécution de la ligne (dans l'autre forme, l'utilisation de guillemets simples a le même effet). Les résultats sont :-

[~/]$ string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
[~/]$ echo $string
"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"
[~/]$ eval 'for word in '$string'; do echo $word; done'
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo
[~/]$ eval "for word in $string; do echo \$word; done"
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo

Comment faire ?

$ for l in "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"; do echo $l; done
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo

Que dois-je faire si ma chaîne est dans un bash variable ?

L'approche simple de l'utilisation du bash string tokenizer ne fonctionnera pas, car il se divise sur chaque espace et pas seulement sur ceux en dehors des guillemets :

[email protected] /f/test
$ cat ./test.sh
#! /bin/bash
string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
for word in $string; do echo "$word"; done

[email protected] /f/test
$ ./test.sh
"aString
that
may
haveSpaces
IN
IT"
bar
foo
"bamboo"
"bam
boo"

Pour contourner ce problème, le script shell suivant (splitstring.sh) montre une approche :

#! /bin/bash 
string=$(cat <<'EOF'
"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo" 
EOF
)
echo Source String: "$string"
results=()
result=''
inside=''
for (( i=0 ; i<${#string} ; i++ )) ; do
    char=${string:i:1}
    if [[ $inside ]] ; then
        if [[ $char == \\ ]] ; then
            if [[ $inside=='"' && ${string:i+1:1} == '"' ]] ; then
                let i++
                char=$inside
            fi
        elif [[ $char == $inside ]] ; then
            inside=''
        fi
    else
        if [[ $char == ["'"'"'] ]] ; then
            inside=$char
        elif [[ $char == ' ' ]] ; then
            char=''
            results+=("$result")
            result=''
        fi
    fi
    result+=$char
done
if [[ $inside ]] ; then
    echo Error parsing "$result"
    exit 1
fi

echo "Output strings:"
for r in "${results[@]}" ; do
    echo "$r" | sed "s/\"//g"
done

Sortie :

$ ./splitstring.sh
Source String: "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"
Output strings:
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo

Source :StackOverflow answer Divisez une chaîne uniquement par des espaces qui sont en dehors des guillemets par choroba. Le script a été modifié pour correspondre aux exigences de la question.


Linux
  1. Comment décomposer un fichier comme Split en Stdout pour le diriger vers une commande ?

  2. Comment écrire une chaîne de plusieurs lignes en utilisant Bash avec des variables ?

  3. Comment exécuter la commande bash avec les privilèges sudo en Java ?

  4. Commande bash alias avec guillemets simples et doubles

  5. Comment exécuter une commande en arrière-plan avec un délai ?

Commande Echo sous Linux (avec exemples)

Commande Echo sous Linux avec exemples

La commande Bash Echo expliquée avec des exemples sous Linux

Comment utiliser la commande echo dans les scripts Bash sous Linux

Comment rechercher des fichiers avec des dizaines de critères avec la commande Bash Find

Commande split Linux avec exemples