variable_list="
any:any:-a -b -c any
one:one:-c -b -f -m mul
mul:one:-c -b -f -m mul
"
for f in `echo $variable_list`
do
c1=`echo $f | cut -d':' -f1`;
c2=`echo $f | cut -d':' -f2`;
c3=`echo $f | cut -d':' -f3-`;
echo "c1==>$c1 and c2==>$c2 and c3==>$c3";
#exit 0; ###I made mistake here
done;
预期输出:
c1==>any and c2==>any and c3==>-a -b -c any
c1==>one and c2==>one and c3==>-c -b -f -m mul
c1==>mul and c2==>one and c3==>-c -b -f -m mul
编辑1:
我意识到我在使用脚本时很愚蠢,并且在第一次迭代时我exit 0
只测试了它的第一行,因为我实际上有很多这样的脚本。它按照它必须的方式工作。
variable_list
我可以通过维护而不修改输入的格式/方式来实现上述输出吗?
(我使用的是bash)
答案1
您的问题与数据中的空格有关。 shell 会将字符串拆分为所有空格上的单词,并且循环for
将迭代这些单词。
(对于不替换variable_list
为数组的解决方案,请参阅此答案的最后部分。)
相反,使用适当的数组:
variable_list=(
"any:any:-a -b -c any"
"one:one:-c -b -f -m mul"
"mul:one:-c -b -f -m mul"
)
for var in "${variable_list[@]}"; do
c1=$( cut -d':' -f1 <<<"$var" )
c2=$( cut -d':' -f2 <<<"$var" )
c3=$( cut -d':' -f3- <<<"$var" )
printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done
使用数组可确保您可以将每个单独的变量集作为其自己的数组条目进行访问,而无需依赖换行符或其他字符分隔它们。
该代码还使用“here-strings”将bash
字符串发送到cut
(而不是echo
管道)。
或者,更有效地,
variable_list=(
"any:any:-a -b -c any"
"one:one:-c -b -f -m mul"
"mul:one:-c -b -f -m mul"
)
for var in "${variable_list[@]}"; do
IFS=':' read -r c1 c2 c3 <<<"$var"
printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done
设置IFS
为冒号 forread
将使read
输入在冒号上分割(而不是在空格、制表符和换行符上)。
请注意,以上所有引用都很重要。如果没有双引号,shell 将对variable_list
、var
和三个c
变量的值执行分词和文件名匹配。
有关的:
如果您所追求的只是特定的输出,那么您可能会作弊:
variable_list=(
"any:any:-a -b -c any"
"one:one:-c -b -f -m mul"
"mul:one:-c -b -f -m mul"
)
( IFS=':'; set -f; printf 'c1==>%s and c2==>%s and c3==>%s\n' ${variable_list[@]} )
这会printf
在子 shell 中运行,以便设置IFS
和-f
( noglob
) shell 选项不会影响脚本的其余部分。此处设置IFS
冒号将使 shell 展开未引用的 variable_list
数组分成三组,每组三个参数printf
。 printf
将根据其格式字符串打印前三个参数,然后为下一组三个参数重用该格式,直到处理完所有参数。
如果其中存在任何文件名通配字符,则可以set -f
防止未加引号的扩展触发文件名通配。variable_list
使用换行符分隔的字符串:
variable_list="
any:any:-a -b -c any
one:one:-c -b -f -m mul
mul:one:-c -b -f -m mul"
while IFS= read -r var; do
IFS=':' read -r c1 c2 c3 <<<"$var"
printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done <<<"$variable_list"
这会从字符串中读取数据,就像它来自文件一样。
有关的:
答案2
您可以使用 awk 来获取输出:
echo "$variable_list" | awk -F: '
{
sub("^ ","")
for(i=1;i<=NF;i++)
sub(/^/,"c" i "==>",$i)
}1' OFS=" and "