2017-02-07 88 views
1

我有這樣preg_match_all等同於BASH?

foo:collection:indexation [options] [--] <text> <text_1> <text_2> <text_3> <text_4> 

一個字符串,我想使用bash正則表達式來得到一個數組或字符串,我可以拆分得到這個以檢查語法是否正確

["text", "text_1", "text_2", "text_3", "text_4"] 

我試圖做到這一點:

COMMAND_OUTPUT=$($COMMAND_HELP) 
# get the output of the help 
# regex 
ARGUMENT_REGEX="<([^>]+)>" 
GOOD_REGEX="[a-z-]" 

# get all the arguments 
while [[ $COMMAND_OUTPUT =~ $ARGUMENT_REGEX ]]; do 
    ARGUMENT="${BASH_REMATCH[1]}" 
    # bad syntax 
    if [[ ! $ARGUMENT =~ $GOOD_REGEX ]]; then 
     echo "Invalid argument '$ARGUMENT' for the command $FILE" 
     echo "Must only use characters [a-z:-]" 
     exit 5 
    fi 
done 

但同時,似乎並不恰當,因爲我總是第一個匹配。

我怎樣才能得到這個正則表達式的所有匹配?

謝謝!

回答

1

循環不起作用,因爲每次你只是測試相同的輸入字符串對正則表達式。它不知道它應該從上次迭代的匹配之後開始掃描。在進行下一次測試之前,您需要刪除字符串的一部分直到幷包括前一場比賽。

更簡單的方法是使用grep -o來獲得所有匹配項。

$COMMAND_HELP | grep -o "$ARGUMENT_REGEX" | while read ARGUMENT; do 
    if [[ ! $ARGUMENT =~ $GOOD_REGEX ]]; then 
     echo "Invalid argument '$ARGUMENT' for the command $FILE" 
     echo "Must only use characters [a-z:-]" 
     exit 5 
    fi 
done 
1

Bash沒有直接的,但你可以通過稍作修改來達到類似的效果。

string='foo...' 
re='<([^>]+)>' 

while [[ $string =~ $re(.*) ]]; do 
    string=${BASH_REMATCH[2]} 

    # process as before 
done 

這符合我們想要一切正則表達式後的字符串中的正則表達式。我們通過在每次迭代時只分配after-our-regex部分來縮短$string。在最後一次迭代中,${BASH_REMATCH[2]}將爲空,因此循環將終止。