在 CI/CD 作業中,我X
定義了一個 shell 變數。它包含一個或多個單詞,每個單詞都可能有全域運算子:
X="foo bar* 'a b c'"
假設bar*
匹配 3 個檔案,bard
,bare
和barf
. 和檔案a b c
存在并且其中有2個空格。
我想Y
用這些內容創建一個 Bash 陣列:
Y=(--arg foo --arg bard --arg bare --arg barf --arg 'a b c')
換句話說:做 glob/quote 擴展,然后將每個單詞映射w
到--arg $w
.
一個干凈的解決方案將允許擴展名稱中的空格(老實說,我永遠不會在此 CI/CD 代碼中遇到這種情況 - 但我或其他人可能會輕松地將這種技術復制/粘貼到其他重要的地方) .
如果我可以在不呼叫所有其他可能的 shell 擴展(例如行程替換和子shell)的情況下進行 glob/quote 擴展,那也很棒 - 不過,我很難考慮如何做到這一點。
到目前為止,我提出的唯一解決方案是使用不受保護的擴展:
Y=()
for a in $X; do
Y =(--arg "$a")
done
這是我能做的最好的嗎?安全嗎?它適用于foo
和bar*
案例,但不適用于a b c
案例。
uj5u.com熱心網友回復:
在尊重引號的同時擴展 glob(用于分組但不是 glob-suppression),但不擴展變數或處理行程替換或其他危險語法......
X="foo bar* 'a b c'"
IFS=
args=( )
while read -r -d '' word; do
for item in $word; do
args =( --arg "$item" )
done
done < <(xargs printf '%s\0' <<<"$X")
在https://replit.com/@CharlesDuffy2/UnlawfulDecentApplicationserver#main.sh的在線沙箱(其中bard
存在)中bare
查看此運行barf
使用xargs printf '%s\0'
has以幾乎xargs
符合 POSIX 的方式進行分詞作業(如果您想要完全符合 POSIX 的內容,則需要使用 Python模塊——網站上的其他問答演示了如何),以及未參考的使用空 IFS 的擴展僅執行 globbing。shlex
uj5u.com熱心網友回復:
以@Fravadona 的回答來回答這個問題。
您必須相信該字串中不會包含任何惡意內容。
這是您需要的情況eval
:給定
$ touch bar{d,e,f}
$ X="foo bar* 'a b c'"
那么這不會讓你得到你想要的:
$ y=($X)
$ declare -p y
declare -a y=([0]="foo" [1]="bard" [2]="bare" [3]="barf" [4]="'a" [5]="b" [6]="c'")
然而
$ eval "y=($X)"
$ declare -p y
declare -a y=([0]="foo" [1]="bard" [2]="bare" [3]="barf" [4]="a b c")
然后
$ Y=(); for elem in "${y[@]}"; do Y =(--arg "$elem"); done
$ declare -p Y
declare -a Y=([0]="--arg" [1]="foo" [2]="--arg" [3]="bard" [4]="--arg" [5]="bare" [6]="--arg" [7]="barf" [8]="--arg" [9]="a b c")
如果你有一個壞演員,你得到了X='nasty $(bad command here)'
,那么你不能使用 eval。
uj5u.com熱心網友回復:
您可以使用declare
具有以下功能的eval
功能:
#!/bin/bash
x="foo bar* 'a b c'"
declare -a x="($x)"
y=()
for a in "${x[@]}"; do y =(--arg "$a"); done
現在歸結為你想要什么,例如,x='$HOME \ \$USER $( ls )'
真正代表......
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/473841.html