GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie teilt man eine Zeichenfolge mit Anführungszeichen (wie Befehlsargumente) in Bash auf?

Die einfachste Lösung besteht darin, ein Array aus den Argumenten in Anführungszeichen zu erstellen, das Sie dann nach Belieben durchlaufen oder direkt an einen Befehl übergeben können.

eval "array=($string)"

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

p.s. Bitte kommentieren Sie, wenn Sie einen einfacheren Weg ohne eval finden .

Bearbeiten:

Aufbauend auf der Antwort von @Hubbitus haben wir eine vollständig bereinigte und korrekt zitierte Version. Hinweis:Dies ist übertrieben und hinterlässt tatsächlich zusätzliche Backslashes in Abschnitten mit doppelten oder einfachen Anführungszeichen vor den meisten Satzzeichen, ist aber unverwundbar für Angriffe.

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

Ich überlasse es dem interessierten Leser, nach eigenem Ermessen zu modifizieren http://ideone.com/FUTHhj


Als ich die Antwort von David Postill sah, dachte ich „das muss doch eine einfachere Lösung geben“. Nach einigem Experimentieren fand ich die folgenden Werke:-

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

Das funktioniert, weil eval erweitert die Zeile (Entfernen der Anführungszeichen und Erweitern von string ), bevor die resultierende Zeile ausgeführt wird (die die Inline-Antwort ist):

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

Eine Alternative, die auf dieselbe Zeile erweitert wird, ist:

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

Hier string wird innerhalb der doppelten Anführungszeichen erweitert, aber die $ muss maskiert werden, damit word in nicht erweitert, bevor die Zeile ausgeführt wird (in der anderen Form hat die Verwendung von einfachen Anführungszeichen den gleichen Effekt). Die Ergebnisse sind:-

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

Wie mache ich das?

$ 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

Was mache ich, wenn mein String in einem bash ist variabel?

Der einfache Ansatz, den bash zu verwenden String-Tokenizer funktioniert nicht, da er bei jedem Leerzeichen aufteilt, nicht nur bei denen außerhalb der Anführungszeichen:

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

Um dies zu umgehen, zeigt das folgende Shell-Skript (splitstring.sh) einen Ansatz:

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

Ausgabe:

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

Quelle:StackOverflow-Antwort Teilen Sie eine Zeichenfolge nur durch Leerzeichen, die sich außerhalb von Anführungszeichen von Choroba befinden. Das Skript wurde an die Anforderungen der Frage angepasst.


Linux
  1. Wie zerlegt man eine Datei wie Split in Stdout, um sie an einen Befehl weiterzuleiten?

  2. Überprüfen Sie, wie lange die Ausführung eines Bash-Skripts mit dem Time-Befehl dauert

  3. So erstellen Sie eine CPU-Spitze mit einem Bash-Befehl

  4. Wie sortiere ich Dateien in Ordnern nach Dateityp auf Bash (mit dem Befehl ‚file‘)?

  5. Wie schreibe ich eine mehrzeilige Zeichenfolge mit Bash mit Variablen?

Echo-Befehl in Linux (mit Beispielen)

Echo-Befehl in Linux mit Beispielen

Bash Echo-Befehl mit Beispielen in Linux erklärt

So verwenden Sie den Echo-Befehl in Bash-Skripten unter Linux

So finden Sie Dateien mit Dutzenden von Kriterien mit dem Bash-Suchbefehl

Linux-Split-Befehl mit Beispielen