我有一个bash变量,它是一个以空格分隔的字符串列表,并且希望循环从该列表一次迭代2个元素。我已经确定列表的长度可以被2整除。所以我想要类似的东西:
x="a bb cccc d"
while read first second; do
echo "($first,$second)"
done <<< $x
输出应该是:
(a,bb)
(cccc,d)
目前上述收益率:
(a,bb cccc d)
注意:我需要在循环中分配$first
和$second
。 echo
作为占位符放入。
我正在寻找一个有效的答案(最好没有柜台)。
答案 0 :(得分:9)
根据您对值的要求,您可以执行以下操作:
$ x="one two buckle myShoe"
$ xargs -n 2 printf "(%s,%s)\n" <<<$x
(one,two)
(buckle,myShoe)
我认为你确实想要将值赋给shell变量,并且预期循环的主体比简单的格式化打印更复杂。实际上,由于printf
会自动重复格式,直到其参数耗尽,上例中的xargs
是不必要的;它可能只是:
printf "(%s,%s)\n" $x
不幸的是,xargs
不是内置的,因此您无法xargs
任意bash管道。你也不能只定义一个shell函数并给它xargs
它的名字。但是,您可以xargs
一个bash子shell,它提供了一个非常通用的解决方案:
# Shell function which takes two arguments
doit() {
echo "Number of arguments: $#"
echo "First argument: $1"
echo "Second argument: $2"
}
# Make the function visible to subshells
export -f doit
x="one two buckle myShoe"
xargs -n2 bash -c 'doit "$@"' _ <<<$x
最后,根据评论中的讨论,您可以使用printf
或xargs
(但可能printf
更有效,因为它是内置的)将列表重组为对,然后将其输入while read
循环:
printf "%s %s\n" $x |
while read -r first second; do
echo "($first,$second)"
done
答案 1 :(得分:2)
shift
和$1
,$2
等set -- $x
将x
的每个部分分配给bash变量$1
,$2
,$3
等。shift <n>
将编号变量向下移动n
。 (即shift 2
将$3
的值移至$1
,将$4
移至$2
等。)x="a bb cccc d"
set -- $x
while [ ! -z "$1" ] # while $1 is not empty
do
# do whatever you want here with $1 and $2. you can take more
# than two at a time by calling shift with a higher argument
# (and use $1, $2, and $3).
echo "($1,$2)"
shift 2
done
打印:
(a,bb)
(cccc,d)
将它们保存到临时变量:
ARGS=( "$@" ) # save the command line args
set -- $x
...
set -- "${ARGS[@]}" # restore them back
答案 2 :(得分:1)
您可以告诉read
阅读特定的字符数:
while read -n4 first second; do echo "($first,$second)"; done <<< "$x"
(a,b)
(c,d)
编辑:对于通用解决方案,请使用awk:
x="aa bb cccc de"
awk '{for (i=1; i<=NF; i+=2) printf "(%s,%s)\n", $i, $(i+1) }' <<< "$x"
(aa,bb)
(cccc,de)
答案 3 :(得分:1)
我会声明你的变量:
x="a b c d"
A=($x)
然后
$ for ((i=0; i<${#A[*]}; i=i+2)); do echo "("${A[$i]},${A[$i+1]}")"; done
(a,b)
(c,d)