例如,我有一個字串/something an-arg=some-value another-arg=another-value。
將an-arg' 的值提取到變數并將another-arg' 的值提取到另一個變數的最直接方法是什么?
為了更好地舉例說明,這就是我需要發生的事情:
STRING="/something an-arg=some-value another-arg=another-value"
AN_ARG=... # <-- do some magic here to extract an-arg's value
ANOTHER_ARG=... # <-- do some magic here to extract another-arg's value
echo $AN_ARG # should print `some-value`
echo $ANOTHER_ARG # should print `another-value`
所以我一直在尋找一種簡單/直接的方法來做到這一點,我嘗試了:
ARG_NAME="an-arg="
AN_ARG=${STRING#*$ARG_NAME}
但是這個解決方案的問題是它會列印出 之后的所有內容an-arg,包括第二個引數的名稱和它的值,例如some-value another-arg=another-value。
uj5u.com熱心網友回復:
讓資料集任意變數會帶來重大的安全風險。您應該為生成的變數添加前綴(前綴至少有一個小寫字符,以將生成的變數保留在命名空間 POSIX 保留以供應用程式使用),或者將它們放在關聯陣列中;下面的第一個例子是后者。
生成關聯陣列
正如您在https://ideone.com/cKcMSM上看到的那樣——
#!/usr/bin/env bash
# ^^^^- specifically, bash 4.0 or newer; NOT /bin/sh
declare -A vars=( )
re='^([^=]* )?([[:alpha:]_-][[:alnum:]_-] )=([^[:space:]] )( (.*))?$'
string="/something an-arg=some-value another-arg=another-value third-arg=three"
while [[ $string =~ $re ]]; do : "${BASH_REMATCH[@]}"
string=${BASH_REMATCH[5]}
vars[${BASH_REMATCH[2]}]=${BASH_REMATCH[3]}
done
declare -p vars # print the variables we extracted
...正確發出:
declare -A vars=([another-arg]="another-value" [an-arg]="some-value" [third-arg]="three" )
...所以你可以參考${vars[an-arg]},${vars[another-arg]}或${vars[third-arg]}。
這避免了原始提案中的錯誤,即字串可以設定對系統有意義的變數——改變PATH,LD_PRELOAD或其他安全敏感值。
生成前綴名稱
以另一種方式執行此操作可能如下所示:
while [[ $string =~ $re ]]; do : "${BASH_REMATCH[@]}"
string=${BASH_REMATCH[5]}
declare -n _newVar="var_${BASH_REMATCH[2]//-/_}" || continue
_newVar=${BASH_REMATCH[3]}
unset -n _newVar
declare -p "var_${BASH_REMATCH[2]//-/_}"
done
...正如您在https://ideone.com/zUBpsC中看到的那樣,它創建了三個單獨的變數,每個變數的名稱都帶有var_前綴:
declare -- var_an_arg="some-value"
declare -- var_another_arg="another-value"
declare -- var_third_arg="three"
uj5u.com熱心網友回復:
假設:
- OP 了解 Charles Duffy 概述的所有問題,但仍需要獨立變數
- 所有變數名都大寫
- 連字符 (
-) 轉換為下劃線 (_) - 變數名和相關值都不包含嵌入的空格
bash使用 namerefs 的一個想法:
unset newarg AN_ARG ANOTHER_ARG 2>/dev/null
STRING="/something an-arg=some-value another-arg=another-value"
read -ra list <<< "${STRING}" # read into an array; each space-delimited item is a new entry in the array
#typeset -p list # uncomment to display contents of the list[] array
regex='[^[:space:]] =[^[:space:]] ' # search pattern: <var>=<value>, no embedded spaces in <var> nor <value>
for item in "${list[@]}" # loop through items in list[] array
do
if [[ "${item}" =~ $regex ]] # if we have a pattern match (<var>=<val>) then ...
then
IFS="=" read -r ndx val <<< "${BASH_REMATCH[0]}" # split on '=' and read into variables ndx and val
declare -nu newarg="${ndx//-/_}" # convert '-' to '_' and assign uppercased ndx to nameref 'newarg'
newarg="${val}" # assign val to newarg
fi
done
這會產生:
$ typeset -p AN_ARG ANOTHER_ARG
declare -- AN_ARG="some-value"
declare -- ANOTHER_ARG="another-value"
筆記:
- 一旦
for回圈處理完成,訪問新變數將需要對新變數的名稱有所了解 - 使用關聯陣列來管理新變數串列使
for回圈后訪問變得相當容易(例如,新變數名稱只是關聯陣列的索引)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/527012.html
標籤:细绳重击壳Unix
