在另一个函数中迭代存储在另一个变量中的$ @

时间:2014-09-16 01:41:53

标签: sh argv

如何在将$@存储到另一个函数中的另一个变量后进行迭代?

注意这是关于sh shell的,而不是bash。

我的代码(超级简化):

#! /bin/sh

set -- a b "c d"

args=

argv() {
  shift # pretend handling options
  args="$@" # remaining arguments
}

fun() {
  for arg in "$args"; do
    echo "+$arg+"
  done
}

argv "$@"
fun

输出:

+b c d+

我想:

+b+
+c d+

特殊变量$@存储保留空格的argv。 for循环可以遍历$@,也可以保留空格。

set -- a b "c d"
for arg in "$@"; do
  echo "+$arg+"
done

输出:

+a+
+b+
+c d+

但是,一旦将$@分配给另一个变量,保留的空白就会消失。

set -- a b "c d"
args="$@"
for arg in "$args"; do
  echo "+$arg+"
done

输出

+a b c d+

没有引号:

for arg in $args; do
  echo "+$arg+"
done

输出:

+a+
+b+
+c+
+d+

在bash中,可以使用数组来完成。

set -- a b "c d"
args=("$@")
for arg in "${args[@]}"; do
  echo "+$arg+"
done

输出:

+a+
+b+
+c d+

可以在sh shell中完成吗?

2 个答案:

答案 0 :(得分:1)

如果您知道shift已执行fun,则可以在shift内再次使用argv

#! /bin/sh

set -- a b "c d"

args=

argv() {
  shifted=1 # pretend handling options
  shift $shifted
}

fun() {
  [ -n $shifted ] && shift $shifted
  for arg; do
    echo "+$arg+"
  done
}

argv "$@"
fun "$@"

输出:

+b+
+c d+

答案 1 :(得分:0)

以下是两个解决方法。两者都有警告。

首先解决方法:在参数之间添加换行符,然后使用read

set -- a b " c d "

args=

argv() {
  shift
  for arg in "$@"; do
    args="$args$arg\n"
  done
}

fun() {
  printf "$args" | while IFS= read -r arg; do
    echo "+$arg+"
  done
}

argv "$@"
fun

输出:

+b+
+ c d +

请注意,即使之前和之后的空格也会被保留。

警告:如果参数包含换行符,则会被搞砸。

第二种解决方法:在参数周围加上引号,然后使用eval

set -- a b " c d "

args=

argv() {
  shift
  for arg in "$@"; do
    args="$args \"$arg\""
  done
}

fun() {
  for arg in "$@"; do
    echo "+$arg+"
  done
}

argv "$@"
eval fun "$args"

警告:如果参数包含引号,那么你就搞砸了。