如何将多个字符串参数 xargs 到一个命令

如何将多个字符串参数 xargs 到一个命令

像这样:

echo $USER $PASSWORD $RESOURCE_MACHINE $SELECT_SQL  $TARGET_MACHINE $INSERT_SQL | xargs -n6 bash -c '/usr/bin/clickhouse-client -u $1 --password $2 -h $3 -q $4 | /usr/bin/clickhouse-client -u $1 --password $2 -h $5 -q $6' bash

每个参数都是一个字符串。

答案1

xargs' 输入需要以非常特定的格式进行格式化。要成为参数的字符串需要用 SPC、TAB、NL(可能还有其他空白字符,具体取决于实现xargs和区域设置)分隔,如果这些字符中的任何一个可能出现在字符串中,则需要用单引号将它们引起来引号、双引号或反斜杠(NL 除外,只能用反斜杠转义)。

反斜杠和引号也需要转义。并且空元素必须用引号引起来,以免被丢弃。

所以在这里,你不能使用echo来以 识别的格式输出单词列表xargs。更一般地说,echo无论如何都不能用于输出任意数据,因为它自己处理反斜杠和/或以-.

在这里,使用bash,您可以定义:

print-for-xargs() {
  local nl=$'\n'
  if (($# > 0)); then
    set -- "${@//\'/\'\\\'\'}"
    printf "'%s'\n" "${@//$nl/\'\\$nl\'}"
  fi
}

该函数以预期的格式打印其参数xargs(将每个参数放在单引号内,单引号和换行符本身用反斜杠引用外部单引号字符串)。

然后,你可以这样做:

print-for-xargs "$USER" \
                "$PASSWORD" \
                "$RESOURCE_MACHINE" \
                "$SELECT_SQL" \
                "$TARGET_MACHINE" \
                "$INSERT_SQL" |
  xargs -n6 bash -c '
    /usr/bin/clickhouse-client -u "$1" --password "$2" -h "$3" -q "$4" |
      /usr/bin/clickhouse-client -u "$1" --password "$2" -h "$5" -q "$6"
    ' bash

还要记住,参数扩展必须bash像大多数其他类似 POSIX 的 shell 中一样加引号。

如果您xargs支持非标准-0选项(对于输入上的 NUL 分隔记录,0 是唯一不能出现在命令参数中的字节值),则可以大大简化为:

print_for_xargs0() {
  [ "$#" -eq 0 ] || printf '%s\0' "$@"
}
print_for_xargs0 "$USER" \
                 "$PASSWORD" \
                 "$RESOURCE_MACHINE" \
                 "$SELECT_SQL" \
                 "$TARGET_MACHINE" \
                 "$INSERT_SQL" |
  xargs -0 -n6 sh -c '
    /usr/bin/clickhouse-client -u "$1" --password "$2" -h "$3" -q "$4" |
      /usr/bin/clickhouse-client -u "$1" --password "$2" -h "$5" -q "$6"
    ' sh

(不需要bash那里,标准sh也可以)

假设您确实需要xargs出于某种原因致电,并且您只是显示一个简化的示例。

在这里,你可以这样做:

  bash -c '
    /usr/bin/clickhouse-client -u "$1" --password "$2" -h "$3" -q "$4" |
      /usr/bin/clickhouse-client -u "$1" --password "$2" -h "$5" -q "$6"
    ' bash "$USER" "$PASSWORD" "$RESOURCE_MACHINE" "$SELECT_SQL" \
           "$TARGET_MACHINE" "$INSERT_SQL"

xargs根本不调用或者:

/usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" \
   -h "$RESOURCE_MACHINE" -q "$SELECT_SQL" |
   /usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" \
   -h "$TARGET_MACHINE" -q "$INSERT_SQL"

无需运行解释器的单独实例bash

另请注意,在所有这些示例中, 的值最终出现在传递给(以及运行 的参数)$PASSWORD的参数中,这是不好的做法,因为命令参数是系统本地的公共知识(它们显示在 的输出中, 并且可能最终出现在审核日志中)。clickhouse-clientbashbashps -f

答案2

如果您被允许使用 GNU Parallel:

echo "$USER $PASSWORD $RESOURCE_MACHINE $SELECT_SQL $TARGET_MACHINE $INSERT_SQL" |
  parallel --colsep ' ' /usr/bin/clickhouse-client -u {1} --password {2} -h {3} -q {4} '|' /usr/bin/clickhouse-client -u {1} --password {2} -h {5} -q {6}

我们假设变量中没有空格。

如果变量中有空格,请选择一个未出现的字符串(例如 :::)并使用它:

echo "$USER:::$PASSWORD:::$RESOURCE_MACHINE:::$SELECT_SQL $TARGET_MACHINE:::$INSERT_SQL" |
  parallel --colsep ':::' /usr/bin/clickhouse-client -u {1} --password {2} -h {3} -q {4} '|' /usr/bin/clickhouse-client -u {1} --password {2} -h {5} -q {6}

但在您的特定情况下,这似乎是多余的,因为您可以直接在命令中使用变量。

/usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" -h "$RESOURCE_MACHINE" -q "$SELECT_SQL" |
  /usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" -h "$TARGET_MACHINE" -q "$INSERT_SQL"

相关内容