GNU/Linux >> Znalost Linux >  >> Linux

Jak rozdělit řetězec s uvozovkami (jako argumenty příkazu) v bash?

Nejjednodušším řešením je vytvořit pole z citovaných argumentů, které pak můžete přepínat, pokud chcete, nebo je předat přímo příkazu.

eval "array=($string)"

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

p.s. Prosím komentujte, pokud najdete jednodušší způsob bez eval .

Upravit:

Na základě odpovědi @Hubbitus máme plně dezinfikovanou a správně citovanou verzi. Poznámka:Toto je přehnané a ve skutečnosti zanechá další zpětná lomítka ve dvojitých nebo jednoduchých uvozovkách před většinou interpunkce, ale je nezranitelný vůči útoku.

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

Nechávám to na zainteresovaném čtenáři, aby si upravil, jak uzná za vhodné http://ideone.com/FUTHhj


Když jsem viděl odpověď Davida Postilla, pomyslel jsem si „musí existovat jednodušší řešení“. Po nějakém experimentování jsem našel následující díla:-

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

To funguje, protože eval rozšíří řádek (odstraní uvozovky a rozšíří string ) před provedením výsledného řádku (což je vložená odpověď):

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

Alternativa, která se rozšiřuje na stejný řádek, je:

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

Zde string je rozšířen v uvozovkách, ale $ musí být escapováno, takže word není rozbalen před provedením řádku (v jiné formě má použití jednoduchých uvozovek stejný účinek). Výsledky jsou:-

[~/]$ 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

Jak to udělám?

$ 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

Co mám dělat, když je můj řetězec v bash proměnná?

Jednoduchý přístup pomocí bash string tokenizer nebude fungovat, protože se rozděluje na každé místo, nejen na ty mimo uvozovky:

[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"

Chcete-li to obejít, následující skript shellu (splitstring.sh) ukazuje jeden přístup:

#! /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

Výstup:

$ ./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

Zdroj:StackOverflow odpověď Rozdělit řetězec pouze na mezery, které jsou mimo uvozovky podle choroby. Skript byl upraven tak, aby odpovídal požadavkům otázky.


Linux
  1. Zkontrolujte, jak dlouho trvá spuštění Bash skriptu s Time Command

  2. Jak vytvořit špičku CPU pomocí příkazu bash

  3. Jak třídit soubory do složek podle typu souboru na bash (pomocí příkazu 'file')?

  1. příkaz tr - jak nahradit řetězec \n skutečným novým řádkem (\n)

  2. Jak spustit příkaz bash s právy sudo v Javě?

  3. příkaz bash alias s jednoduchými i dvojitými uvozovkami

  1. Jak napsat víceřádkový řetězec pomocí Bash s proměnnými?

  2. Zachovat uvozovky v argumentech bash

  3. Jak mohu zkontrolovat doslovné znaky řetězce příkazu bash?