在bash中一次循环变量2元素

时间:2014-03-05 13:58:29

标签: bash loops

我有一个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$secondecho作为占位符放入。 我正在寻找一个有效的答案(最好没有柜台)。

4 个答案:

答案 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

最后,根据评论中的讨论,您可以使用printfxargs(但可能printf更有效,因为它是内置的)将列表重组为对,然后将其输入while read循环:

printf "%s %s\n" $x |
while read -r first second; do
  echo "($first,$second)"
done

答案 1 :(得分:2)

使用shift$1$2

  • 您可以使用set -- $xx的每个部分分配给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)