sh에서 변수를 명령 옵션 매개변수로 분할

sh에서 변수를 명령 옵션 매개변수로 분할

스크립트 호출에서 변수를 반복 매개변수로 변환하는 가장 효율적인 방법을 알려줄 수 있는 사람이 있나요? 나는 그것을 적절하게 설명하는 방법을 모르지만 예제는 그 자체로 말해줍니다. 적어도 나는 그들이 그러기를 바란다 :)

예시 1:

# input
export DOMAINS="domain1.tld,domain2.tld"

# tranform to
./example-script.sh -d "domain1.tld" -d "domain2.tld"

예 2(입력은 홀수임):

# input
export DOMAINS="domain1.tld"

# tranform to
./example-script.sh -d "domain1.tld"

[업데이트] 첫 번째 게시물에 이 내용을 추가하지 못해 죄송합니다.

추가해야 할 컨텍스트:

  • DOMAINS는 Docker 컨테이너에 추가된 환경 변수입니다.
  • sh컨테이너에는 셸만 있으므로 zsh특정 bash옵션은 효과가 없습니다.
  • 초기 bash태그를 추가해서 죄송합니다.

답변1

다음을 사용하는 것이 더 쉽습니다 zsh.

분리된 목록을 포함하는 스칼라 변수에서 ,:

DOMAINS="domain1.tld,domain2.tld"

s배열로 분할 ,:

domains=( ${(s[,])DOMAINS} )

압축배열 opt=( -d ):

opt=( -d )
./example-script.sh ${opt:^^domains}

이것이 외에 지원되는 경우 ./example-script.sh중간 배열을 건너뛰고 다음을 사용할 수 있습니다.-ddomain1.tld-d domain1.tld

./example-script.sh -d$^domains

Bash에서는 루프를 사용할 수 있습니다.

IFS=, # split on ,
set -o noglob # disable glob
domains=( $DOMAINS ) # split+glob
args=()
for domain in "${domains[@]}"; do
  args+=( -d "$domain" )
done
./example-script.sh "${args[@]}"

또는 셸 구문을 사용하여 코드를 생성할 수 있습니다.

IFS=, # split on ,
set -o noglob # disable glob
domains=( $DOMAINS ) # split+glob
if [ "${#domains[@]}" -gt 0 ]; then
  printf -v args ' -d %q' "${domains[@]}"
else
  args=
fi
shell_code="./example-script.sh$args"
eval -- "$shell_code"

이것이 추가로 지원되는 경우 ./example-script.sh다음을 수행할 수도 있습니다.-ddomain1.tld-d domain1.tld

IFS=, # split on ,
set -o noglob # disable glob
domains=( $DOMAINS ) # split+glob
./example-script.sh "${domains[@]/#-d}"

-d배열의 각 요소 앞에 추가합니다 $domains.

표준에는 sh배열이 없고 표준 read -A/-aprintf없습니다 %q(그리고 이를 확장으로 지원하는 구현이 항상 sh호환 가능한 참조를 생성하는 것은 아닙니다). 대신 위의 첫 번째 bash 메서드를 사용할 수 있습니다 "$@".

IFS=, # split on ,
set -o noglob # disable glob
set --
for domain in $DOMAINS; do # split+glob
  set -- "$@" -d "$domain"
done
./example-script.sh "$@"

또 다른 옵션은 분할을 호출 awk하고 sh호환 가능한 코드를 생성하는 것입니다.

eval "./example-script.sh$(
  LC_ALL=C awk -v q="'" '
    function shquote(s) {
      gsub(q, q "\\\\" q q, s)
      return q s q
    }
    BEGIN {
      n = split(ENVIRON["DOMAINS"], domains, ",")
      for (i = 1; i <= n; i++)
        printf " -d %s", shquote(domains[i])
    }'
)"

답변2

다음과 같이 시도해 보세요.

domains=( "domain1.tld" "domain2.tld" )
./example-script.sh $(printf -- '-d "%s" ' "${domains[@]}")

답변3

표시했으므로 bash해당 셸에 대한 배열 기반 솔루션은 다음과 같습니다.

DOMAINS="domain1.tld,domain2.tld"

# Comma separated string to array
IFS=, read -r -a domains <<<"$DOMAINS"

# Array to parameter list
args=()
for domain in "${domains[@]}"; do args+=(-d "$domain"); done

그런 다음 해당 목록을 결과 명령에 삽입할 수 있습니다 "${args[@]}"(큰따옴표 포함). 예를 들어,

./example-script.sh "${args[@]}"

관련 정보