it-roy-ru.com

Цикл через переменную Shell через запятую

Предположим, у меня есть переменная оболочки Unix, как показано ниже

variable=abc,def,ghij

Я хочу извлечь все значения (abc, def и ghij) с помощью цикла for и передать каждое значение в процедуру. 

Скрипт должен позволять извлекать произвольное количество значений через запятую из $variable.

55
Ramanathan K

Вы можете использовать следующий скрипт для динамического перемещения через вашу переменную, независимо от того, сколько полей у нее есть, если только она разделена запятой. 

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

Вместо вызова echo "$i" выше, между do и done внутри цикла for, вы можете вызвать вашу процедуру proc "$i".


Обновление : Приведенный выше фрагмент работает, если значение переменной не содержит пробелов. Если у вас есть такое требование, используйте одно из решений, которое может изменить IFS, а затем проанализируйте вашу переменную.


Надеюсь это поможет.

71
anacron

Не возиться с IFS
Не вызывать внешнюю команду

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

Использование манипуляции строк bash http://www.tldp.org/LDP/abs/html/string-manipulation.html

88
neric

Если вы установите другой разделитель полей, вы можете напрямую использовать цикл for:

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

Вы также можете сохранить значения в массиве, а затем перебрать их, как указано в Как разделить строку на разделитель в Bash? :

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

Тестовое задание

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

В этом решении вы можете найти более широкий подход к Как перебрать список через запятую и выполнить команду для каждой записи .

Примеры по второму подходу:

$ 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

Я предпочитаю использовать tr вместо sed, потому что у sed есть проблемы со специальными символами, такими как\r\n в некоторых случаях.

другое решение состоит в том, чтобы установить IFS для определенного разделителя

4
Marek Lisiecki

Другое решение, не использующее IFS и сохраняющее пробелы:

$ 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

Попробуй это.

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

Вот альтернативное решение на основе tr, которое не использует эхо, выраженное в виде одной строки.

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

Чувствуется себя лучше без эха, но это мое личное предпочтение.

0
6EQUJ5