Bash 正則表達式和 IFS 拆分
我有以下問題:我想從字元串中提取括號內的文本(帶或不帶括號)。我的字元串如下所示:
STR="[1] [2][345] [678 9] foo bar"
我最初想使用 bash 正則表達式和 BASH_REMATCH。我最終使用了以下程式碼:
regex='\[([^\]]*)\](.*)' MATCHES=() STR="[1] [2][345] [678 9] foo bar" while [[ -n $STR && $STR =~ $regex ]]; do MATCHES+=("${BASH_REMATCH[1]}") STR=${BASH_REMATCH[2]} echo -e "matches: ${BASH_REMATCH[1]} -> ${BASH_REMATCH[2]}" done
這種工作但我的問題是它只會在括號內擷取一個字元,因此
[345]
會導致3
.我不知道為什麼會這樣,所以我最終還是使用了 grep 和 PCRE。我目前的解決方案是
regex="\[[^\]]*?\]" if [[ $(grep -o '\[.*\]' <<< $STR) ]]; then MATCHES=$(grep -oP "$regex" <<< $STR) else echo "No special flags provided." exit 0 fi
然後我進行一個 for 循環:
for arg in $MATCHES; do echo $arg done
問題是它沒有像我希望的那樣分隔欄位。我使用 hexdump 來找出正確的分隔符:
hexdump -C <<< $MATCHES
令我驚訝的是,這表明分隔符是十六進制
0a
的,即LF。這不是問題,因為我知道 for 循環使用 IFS 進行拆分。然後我通過使用將 IFS 設置為 LFIFS=$'\n'
。令我(再次)驚訝的是,0a0a
再次根據 hexdump 將 IFS 的值設置為 。所以那沒有用。然後我將 IFS 的值設置為,IFS=''
並且(對於我的第三個驚喜)將值設置為0a
. 但這也不起作用, for 循環沒有改變行為。也許我的腳本沒有正確設置 IFS 的範圍?我的問題如下:
為什麼原來的 bash only 正則表達式方法不起作用?為什麼它只擷取一個字元?regex101 dot com 顯示了預期的行為,但話又說回來,它不提供 bash 正則表達式模式。
為什麼 IFS 設置不能像我預期的那樣工作?它添加了一個“額外的”LF,即使我將它設置為空。
3)為什麼 IFS 似乎不影響 for 循環?
4)我是否有更簡單的方法來解決原始問題(
[foo] [bar] [foo bar]
從字元串[foo] [bar] 1 asdf[foo bar]
中提取,我可以為每個括號對循環)。獎金問題!
B) 我對何時應該將變數或表達式括在引號或雙引號中感到困惑。我已經閱讀了一些關於 globbing 和參數擴展的內容,現在我正在尋找更深入的內容。有什麼建議嗎?
要匹配任何不包含 a 的非空字元串
]
,請使用[^]]+
.Using
[^\]]*
將匹配一個非\
後跟零個或多個]
. 這就是為什麼您設法解析出 the1
和 the2
而不是其他字元串的原因。該
IFS
變數不會在您的第一段程式碼中發揮作用。裡面的變數[[ ... ]]
不需要雙引號。要列印數組的單獨元素,請使用
printf '%s\n' "${MATCHES[@]}"
或者
for elem in "${MATCHES[@]}"; do printf '%s\n' "$elem" done
只是
$MATCHES
將擴展為僅數組的第一個元素(並將對值應用分詞和文件名萬用字元)。