Shell-Script

將變數拆分為 sh 中的命令選項參數

  • November 2, 2022

誰能告訴我在腳本呼叫中將變數轉換為重複參數的最有效方法?我不知道如何正確描述它,但例子不言自明。至少我希望他們這樣做:)

範例 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"

$$ UPDATE $$ 我很抱歉沒有在第一篇文章中添加這個。 我應該添加的上下文:

  • DOMAINS 是添加到 Docker 容器的環境變數
  • 容器只有sh外殼,因此zsh特定bash選項不起作用。
  • 很抱歉添加了初始bash標籤。

它更容易zsh

從包含,-separated 列表的標量變數中:

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[@]}"

或者,您可以使用 shell 語法生成程式碼:

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/-a,標準printf也沒有%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])
   }'
)"

引用自:https://unix.stackexchange.com/questions/723387