有沒有辦法從以下字串分配多個變數?
edit "admin1" edit "admin2" edit "admin3"
我想擁有
var1=admin1 var2=admin2 var3=admin3
謝謝。
uj5u.com熱心網友回復:
嘗試這個:
read -r trash var1 trash var2 trash var3 <<< $(echo edit "admin1" edit "admin2" edit "admin3")
uj5u.com熱心網友回復:
請您嘗試以下方法:
#!/bin/bash
str='edit "admin1" edit "admin2" edit "admin3"' # input string
pat='[^"]*"([^"]*)"(.*)' # regex to match the string
while [[ $str =~ $pat ]]; do # match the regex
printf -v 'var'$(( n)) "${BASH_REMATCH[1]}"
# assign varN to the matched substring
str="${BASH_REMATCH[2]}" # update "str" by truncating left to right
done <<< "$str"
# see the results
echo "$var1"
echo "$var2"
echo "$var3"
上面腳本的好處是你不需要提前知道變數的數量。
正則運算式的解釋pat:
[^"]*匹配零個或多個除雙引號以外的任何字符的序列。它可以跳過額外的字串,例如edit."([^"]*)"匹配用雙引號括起來的字串。Bash 變數${BASH_REMATCH[1]}會自動分配給封閉的字串,因為模式用括號括起來。(.*)匹配剩余的子字串。該變數str被重新分配給它(被截斷)以在下一個while回圈中使用。while回圈保持匹配正則運算式,pat直到str沒有匹配。
然后該陳述句printf -v 'var'$(( n)) "${BASH_REMATCH[1]}"生成一個變數
var1, var2, var3, .. 將它們按順序分配給用雙引號括起來的字串。
這是正則運算式如何在回圈中作業的說明:
第一個回圈:
編輯“admin1” 編輯“admin2” 編輯“admin3”
<---> <----> <--------------->
跳過 | |
BASH_REMATCH[1] BASH_REMATCH[2]
var1 := BASH_REMATCH[1]
str := BASH_REMATCH[2]
第二個回圈:
編輯“admin2” 編輯“admin3”
<----> <----> <------------>
跳過 | |
BASH_REMATCH[1] BASH_REMATCH[2]
var2 := BASH_REMATCH[1]
str := BASH_REMATCH[2]
第三個回圈:
編輯“admin3”
<----> <---->
跳過 |
BASH_REMATCH[1]
var3 := BASH_REMATCH[1]
str := 空
uj5u.com熱心網友回復:
有很多方法可以做到這一點,但這實際上取決于資料的可變性以及決議輸入的可靠性。鑒于上面的示例,以下使用 read 內置字串和行程替換將起作用:
read var1 var2 var3 < \
<(sed -r 's/edit ?//g' <<< 'edit "admin1" edit "admin2" edit "admin3"')
echo $var1; echo $var2; echo $var3
這將正確列印:
"admin1"
"admin2"
"admin3"
您還可以將輸入收集為索引或關聯陣列,或使用間接變數擴展。但是,如果您的實際輸入更復雜,您最大的挑戰將是僅掃描引號中的單詞,并且可能會以一種或另一種形式涉及大量拆分和回圈。
uj5u.com熱心網友回復:
這個Shellcheck -clean 演示程式使用 Bash 中內置的正則運算式支持:
#! /bin/bash -p
edit_rx='edit[[:space:]] "([^"]*)"'
all_edits_rx="${edit_rx}[[:space:]] ${edit_rx}[[:space:]] ${edit_rx}"
teststr='edit "admin1" edit "admin2" edit "admin3"'
if [[ $teststr =~ $all_edits_rx ]]; then
var1=${BASH_REMATCH[1]}
var2=${BASH_REMATCH[2]}
var3=${BASH_REMATCH[3]}
else
printf "ERROR: '%s' does not match '%s'\\n" "$all_edits_rx" "$teststr" >&2
exit 1
fi
declare -p var1 var2 var3
這種方法的一個優點是它會徹底檢查輸入是否具有預期的格式,從而最大限度地減少垃圾輸入、垃圾輸出的風險。
如果字串中參考值的數量并不總是 3(甚至可能總是 3),那么將值放在陣列中而不是編號變數中會更好。這個Shellcheck -clean 演示程式顯示了一種方法:
#! /bin/bash -p
editlist_rx='^edit[[:space:]] "([^"]*)"[[:space:]]*(.*)$'
teststr='edit "admin1" edit "admin2" edit "admin3" edit "admin4" edit "admin5"'
tmp=$teststr
vars=()
while [[ $tmp =~ $editlist_rx ]]; do
vars =( "${BASH_REMATCH[1]}" )
tmp=${BASH_REMATCH[2]}
done
if [[ -n $tmp ]]; then
printf "ERROR: failed match at '%s'\\n" "$tmp" >&2
exit 1
fi
for i in "${!vars[@]}"; do
printf 'vars[%d]=%q\n' "$i" "${vars[i]}"
done
它輸出:
vars[0]=admin1
vars[1]=admin2
vars[2]=admin3
vars[3]=admin4
vars[4]=admin5
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/432244.html
