假设我有一个Unix shell变量,如下所示
variable=abc,def,ghij
我想使用for循环提取所有值(abc
,def
和ghij
)并将每个值传递给过程。
该脚本应允许从$variable
中提取任意数量的逗号分隔值。
答案 0 :(得分:96)
没有弄乱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
答案 1 :(得分:76)
只要逗号分隔,您可以使用以下脚本动态遍历变量,无论它有多少个字段。
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
调用,在{for循环中done
和proc "$i"
之间调用。
更新:如果变量的值不包含空格,则上述代码段有效。如果您有这样的要求,请使用其中一个可以更改IFS
然后解析变量的解决方案。
希望这有帮助。
答案 2 :(得分:39)
如果您设置了不同的字段分隔符,则可以直接使用for
循环:
IFS=","
for v in $variable
do
# things with "$v" ...
done
您还可以将值存储在数组中,然后按照How do I split a string on a delimiter in 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
您可以在How to iterate through a comma-separated list and execute a command for each entry的此解决方案中找到更广泛的方法。
第二种方法的例子:
$ 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 --
答案 3 :(得分:4)
#/bin/bash
TESTSTR="abc,def,ghij"
for i in $(echo $TESTSTR | tr ',' '\n')
do
echo $i
done
我更喜欢使用tr而不是sed,因为在某些情况下,像\ r \ n之类的特殊字符有问题。
其他解决方案是将IFS设置为某个分隔符
答案 4 :(得分:0)
试试这个。
#/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
答案 5 :(得分:0)
另一种不使用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
答案 6 :(得分:0)
这是基于tr的替代解决方案,它不使用回声(表示为单线)。
for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done
感觉没有回声,但那只是我个人的喜好。
答案 7 :(得分:0)
这是我的纯bash解决方案,它不会更改IFS,并且可以采用自定义的正则表达式定界符。
loop_custom_delimited() {
local item
for item in $(echo $2 | sed 's/ /'`echo -e "\010"`'/g' | sed -E "s/$1/ /g"); do
item=$(echo $item | sed 's/'`echo -e "\010"`'/ /g')
eval "${3:-"$item"}"
done
}
loop_custom_delimited ',' "a,b 1,b 2" 'echo $item'
echo ""
loop_custom_delimited ',' 'echo a,echo b 1,echo "b 2"'
echo ""
loop_custom_delimited ':([0-9]+)?(\.?[0-9]+):' "a:12.34:b 1:.1:b 2" 'echo "$item"'
echo ""
loop_custom_delimited ':([0-9]+)?(\.?[0-9]+):' 'echo a:1.3:echo b 1:4:echo b 2'
答案 8 :(得分:0)
以下解决方案:
IFS
i
循环中的 for
)[:,]
这样的括号表达式)nocasematch
打开时可能出现的任何细微问题,并且在匹配中使用具有小写/大写版本的分隔符,例如 ${parameter/pattern/string}
或 {{1} }注意:
case
已设置,如果未设置且 var
有效,则会失败set -u
请注意,需要相应地引用模式中特殊字符的分隔符(例如文字 while true; do
x="${var%%,*}"
echo $x
#x is not really needed here, one can of course directly use "${var%%:*}"
if [ -z "${var##*,*}" ] && [ -n "${var}" ]; then
var="${var#*,}"
else
break
fi
done
)。