여러 문자열 인수를 하나의 명령으로 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' 입력은 매우 구체적인 형식으로 지정되어야 합니다. 매개변수가 될 문자열은 xargsSPC, TAB, NL(및 구현 및 로캘에 따라 다른 공백 문자)로 구분해야 하며 이러한 문자가 문자열에 나타날 수 있는 경우 작은따옴표로 묶어야 합니다. 따옴표, 큰따옴표 또는 백슬래시(백슬래시로만 이스케이프할 수 있는 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 유사 셸에서처럼 인용되어야 한다는 점을 기억하세요.

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 병렬 사용이 허용된 경우:

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"

관련 정보