【问题标题】:Is there a way to pass multiple argument as a single string in bash?有没有办法在bash中将多个参数作为单个字符串传递?
【发布时间】:2022-06-10 18:57:43
【问题描述】:

我正在运行一个程序,该程序接受具有相同标志的可变数量的参数。例如

myprogram -args 'var1' 'var2' 'var3' 'var4'
myprogram -args 'var5' 'var6'

我必须使用 test.txt 文件中提供的不同参数集多次启动该程序。

arg1 arg2 arg3
arg5 arg6
arg7
arg8 arg9 arg9 arg10

程序必须在自己的脚本中才能请求 HPCC 中的资源。

while read p; do
  launchmyprogram.sh "$p"
done < test.txt

我知道我可以在launchmyprogram.sh 中使用var1=$1 语法来收集和分配变量,但这不能处理可变数量的参数,我必须为每一行创建一个脚本。有没有办法在 bash 中创建一个接受可变数量参数的脚本?

【问题讨论】:

  • 目前尚不完全清楚问题是什么,但也许这只是一个您想要避免引号并执行launchmyprogram.sh $p 以便test.txt 中的行的每个单词都传递为一个单独的论点。
  • 不要在脚本名称上使用.sh 后缀:talisman.org/~erlkonig/documents/…
  • 一个数组将保留对单个元素的引用...请参阅下面 Andrej 的答案。
  • 参数可以包含空格吗?如果是这样,您是否在text.txt 中引用它?

标签: linux bash hpcc


【解决方案1】:

使用数组来存储动态大小的字符串序列。 Bash 有两种将输入读入数组的方式:

  • readarray -t somearray 将整个输入文件的行转换为数组元素。
  • read -a somearray 将单行输入的标记转换为数组元素。

在这种情况下,您可以使用后者。这是一个可运行的 MWE:

myprogram() {
  local -i i
  echo "Got ${#} arguments."
  for ((i = 1; i <= $#; ++i)); do
    echo "Argument No. ${i} is '${!i}'."
  done
}

while read -ra args; do
  myprogram -args "${args[@]}"
done <<-INPUT
    arg1 arg2 arg3
    arg5 arg6
    arg7
    arg8 arg9 arg9 arg10
INPUT

这样,每一行的参数都是分开的,正如输出所示:

Got 4 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg1'.
Argument No. 3 is 'arg2'.
Argument No. 4 is 'arg3'.
Got 3 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg5'.
Argument No. 3 is 'arg6'.
Got 2 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg7'.
Got 5 arguments.
Argument No. 1 is '-args'.
Argument No. 2 is 'arg8'.
Argument No. 3 is 'arg9'.
Argument No. 4 is 'arg9'.
Argument No. 5 is 'arg10'.

【讨论】:

    【解决方案2】:

    您可以使用$# 来查询传递给launchmyprogram.sh 的参数数量。类似的东西

    if [ $# -eq 1 ]; then
      echo "one argument"
    elif [ $# -eq 2 ]; then
      echo "two arguments"
    elif [ $# -eq 3 ]; then
      echo "three arguments"
    else
        echo "too many arguments"
        exit 1
    fi
    

    【讨论】:

      【解决方案3】:

      所有 bash 脚本都采用可变数量的参数,您的问题是如何访问它们。最简单的方法是:

      for arg; do
          my-cmd "$arg"
      done
      

      这对每个参数单独重复my-cmd。您可以在launchmyprogram.sh 中使用此循环。您也可以将相关代码放在一个函数中,并在循环中只使用该函数。

      从文件中解析参数更加复杂。如果没有为 shell 引用参数,并且不包含空格或通配符 ([]?*),您可以在示例中取消引用 $p。它将在空白处拆分为多个参数。

      在这种情况下,您也可以只解析 launchmyprogram.txt 中的整个文件:

      for arg in $(<test.txt); do
          my-cmd "$arg"
      done
      

      【讨论】:

        【解决方案4】:

        这基本上 Andrej 的答案,但为了简化并使其与问题的结构更直接相关 -

        while read -ra p; do         # read and parse line into an array
          myprogram -args "${p[@]}"  # pass elements as separate values
        done < test.txt              # after reading them in as one line
        

        【讨论】:

          【解决方案5】:

          使用xargs 可能是最简单的解决方案:

          xargs -L 1 myprogram -args < test.txt
          

          给定您的示例test.txt,这相当于运行:

          myprogram -args arg1 arg2 arg3       < /dev/null
          myprogram -args arg5 arg6            < /dev/null
          myprogram -args arg7                 < /dev/null
          myprogram -args arg8 arg9 arg9 arg10 < /dev/null
          

          这有一个限制:

          -L号
          该实用程序应针对标准输入中的每个非空行参数执行。

          这意味着所有的空行都会被跳过,所以在上面的例子中,你不能让xargs运行简单的myprogram -args(没有更多参数)。

          关于xargs的输入格式:

          标准输入中的参数由不带引号的 blank 字符、未转义的 blank 字符或 newline 字符分隔。
          零个或多个非双引号 (") 字符和非newline 字符的字符串可以通过将它们括在双引号中来引用。
          零个或多个非apostrophe (') 字符和非newline 字符的字符串可以通过将它们括在apostrophe 字符中来引用。
          任何未加引号的字符都可以通过在其前面加上 backslash ( \ ) 进行转义。

          这很好,因为它允许您指定任意字符串(不包含空字节)作为myprogram -args 的附加参数,前提是您正确地进行了转义;另一方面,如果您不了解转义规则,则可能适得其反。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-07-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-07-10
            • 2015-02-06
            相关资源
            最近更新 更多