Петля через переменную оболочки, разделенную запятой
Предположим, что у меня есть переменная оболочки Unix, как показано ниже
variable=abc,def,ghij
Я хочу извлечь все значения (abc
, def
и ghij
) с помощью цикла for и передать каждое значение в процедуру.
script должен разрешить извлечение произвольного количества разделенных запятыми значений из $variable
.
Ответы
Ответ 1
Вы можете использовать следующий script, чтобы динамически перемещаться по вашей переменной, независимо от того, сколько полей оно имеет, если оно только разделено запятой.
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
, а затем проанализировать вашу переменную.
Надеюсь, что это поможет.
Ответ 2
Не возиться с 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
Ответ 3
Если вы установите другой разделитель полей, вы можете напрямую использовать цикл 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
Test
$ 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 --
Ответ 4
#/bin/bash
TESTSTR="abc,def,ghij"
for i in $(echo $TESTSTR | tr ',' '\n')
do
echo $i
done
Я предпочитаю использовать tr вместо sed, потому что sed sed имеет проблемы со специальными символами, такими как \r\n в некоторых случаях.
другим решением является установка IFS для определенного разделителя
Ответ 5
Попробуйте это.
#/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
Ответ 6
Другое решение, не использующее 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
Ответ 7
Вот альтернативное решение на основе tr, которое не использует эхо, выраженное в виде одной строки.
for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done
Чувствуется себя лучше без эха, но это мое личное предпочтение.