web-dev-qa-db-de.com

Durchlaufen Sie eine durch Kommas getrennte Shell-Variable

Angenommen, ich habe eine Unix-Shell-Variable wie unten

variable=abc,def,ghij

Ich möchte alle Werte (abc, def und ghij) mithilfe einer for-Schleife extrahieren und jeden Wert in eine Prozedur übergeben. 

Das Skript sollte das Extrahieren einer beliebigen Anzahl von durch Kommas getrennten Werten aus $variable ermöglichen.

55
Ramanathan K

Sie können das folgende Skript verwenden, um dynamisch durch Ihre Variable zu navigieren, unabhängig davon, wie viele Felder es enthält, solange es nur durch Kommas getrennt ist. 

variable=abc,def,ghij
for i in $(echo $variable | sed "s/,/ /g")
do
    # call your procedure/other scripts here below
    echo "$i"
done

Anstelle des echo "$i"-Aufrufs oben zwischen der do und done in der for-Schleife können Sie Ihre Prozedur proc "$i" aufrufen.


Update : Das obige Snippet funktioniert, wenn der Wert der Variablen keine Leerzeichen enthält. Wenn Sie eine solche Anforderung haben, verwenden Sie eine der Lösungen, die IFS ändern kann, und parsen Sie Ihre Variable.


Hoffe das hilft.

71
anacron

Nicht mit IFS herumspielen
Externen Befehl wird nicht aufgerufen

variable=abc,def,ghij
for i in ${variable//,/ }
do
    # call your procedure/other scripts here below
    echo "$i"
done

Verwenden der Bash-String-Manipulation http://www.tldp.org/LDP/abs/html/string-manipulation.html

88
neric

Wenn Sie ein anderes Feldtrennzeichen festlegen, können Sie eine for-Schleife direkt verwenden:

IFS=","
for v in $variable
do
   # things with "$v" ...
done

Sie können die Werte auch in einem Array speichern und dann wie in durchlaufen durchlaufen. Wie teile ich einen String in einem Trennzeichen in Bash auf? :

IFS=, read -ra values <<< "$variable"
for v in "${values[@]}"
do
   # things with "$v"
done

Prüfung

$ variable="abc,def,ghij"
$ IFS=","
$ for v in $variable
> do
> echo "var is $v"
> done
var is abc
var is def
var is ghij

In dieser Lösung finden Sie einen umfassenderen Ansatz für How, um eine durch Kommas getrennte Liste zu durchlaufen und einen Befehl für jeden Eintrag auszuführen.

Beispiele zum zweiten Ansatz:

$ IFS=, read -ra vals <<< "abc,def,ghij"
$ printf "%s\n" "${vals[@]}"
abc
def
ghij
$ for v in "${vals[@]}"; do echo "$v --"; done
abc --
def --
ghij --
34
fedorqui
#/bin/bash   
TESTSTR="abc,def,ghij"

for i in $(echo $TESTSTR | tr ',' '\n')
do
echo $i
done

Ich bevorzuge die Verwendung von tr anstelle von sed, da sed in einigen Fällen Probleme mit Sonderzeichen wie\r\n hat.

eine andere Lösung besteht darin, IFS auf ein bestimmtes Trennzeichen zu setzen

4
Marek Lisiecki

Eine andere Lösung, die IFS nicht verwendet und die Leerzeichen trotzdem beibehält:

$ var="a bc,def,ghij"
$ while read line; do echo line="$line"; done < <(echo "$var" | tr ',' '\n')
line=a bc
line=def
line=ghij
0
user3071170

Probier diese.

#/bin/bash   
testpid="abc,def,ghij" 
count=`echo $testpid | grep -o ',' | wc -l` # this is not a good way
count=`expr $count + 1` 
while [ $count -gt 0 ]  ; do
     echo $testpid | cut -d ',' -f $i
     count=`expr $count - 1 `
done
0
Karthikeyan.R.S

Hier ist eine alternative tr-basierte Lösung, die kein Echo verwendet, ausgedrückt als Einzeiler.

for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done

Es fühlt sich sauberer an ohne Echo, aber das ist nur meine persönliche Vorliebe.

0
6EQUJ5