2012-07-19 40 views
1

一直在尋找一些關於bash的正則表達式的更高級的正則表達式信息,並沒有找到關於它的很多信息。在bash中使用正則表達式的字符串中的多個匹配

這裏的概念,用一個簡單的字符串:

myString="DO-BATCH BATCH-DO" 

if [[ $myString =~ ([[:alpha:]]*)-([[:alpha:]]*) ]]; then 
echo ${BASH_REMATCH[1]} #first perens 
echo ${BASH_REMATCH[2]} #second perens 
echo ${BASH_REMATCH[0]} #full match 
fi 

outputs: 
BATCH 
DO 
DO-BATCH 

那麼細它的第一場比賽(批次DO),但我怎麼拉第二場比賽(DO-批)?我只是在這裏畫一個空白,找不到關於bash正則表達式的很多信息。

+1

由於您的字符串中沒有出現「DO-BATCH」,因此您不清楚您在詢問什麼。但是,你的意思是你還希望'$ {BASH_REMATCH [3]}'等於「BATCH」等? – chepner 2012-07-19 17:26:54

+0

糟糕你的正確...編輯OP。是的,這是正確的 - > $ {BASH_REMATCH [3]} ==「BATCH」和$ {BASH_REMATCH [4]} ==「DO」 – 2012-07-19 18:00:12

回答

2

行,所以我做了這一個辦法是把它放在一個for循環:

myString="DO-BATCH BATCH-DO" 
for aString in ${myString[@]}; do 
    if [[ ${aString} =~ ([[:alpha:]]*)-([[:alpha:]]*) ]]; then 
    echo ${BASH_REMATCH[1]} #first perens 
    echo ${BASH_REMATCH[2]} #second perens 
    echo ${BASH_REMATCH[0]} #full match 
    fi 
done 

which outputs: 
DO 
BATCH 
DO-BATCH 
BATCH 
DO 
BATCH-DO 

哪些工作,但我有點希望如果可能的話把它拉都來自同一個正則表達式。

+0

'perl'支持通過其「g」標誌重複匹配的概念匹配運算符'm //',但據我所知,'bash'沒有相同的結果。 – chepner 2012-07-19 18:38:35

1

在你的回答中,myString不是一個數組,但是你使用一個數組引用來訪問它。這在Bash中起作用,因爲數組的第0個元素只能通過變量名引用,反之亦然。這意味着你可以使用:

for aString in $myString; do 

在這種情況下得到相同的結果。

在你的問題中,你說輸出包括「BATCH-DO」。我得到「DO-BATCH」,所以我認爲這是一個錯字。

獲得額外字符串而不使用for循環的唯一方法是使用更長的正則表達式。順便說一下,我建議把Bash正則表達式放在變量中。它使某些類型更容易使用(那些包含空格或特殊字符,例如

pattern='(([[:alpha:]]*)-([[:alpha:]]*)) +(([[:alpha:]]*)-([[:alpha:]]*))' 
[[ $myString =~ $pattern ]] 
declare -p BASH_REMATCH #dump the array 

輸出:

declare -ar BASH_REMATCH='([0]="DO-BATCH BATCH-DO" [1]="DO-BATCH" [2]="DO" [3]="BATCH" [4]="BATCH-DO" [5]="BATCH" [6]="DO")' 

,如果你想捕捉的個體所需要的額外的括號子字符串以及帶連字符的短語如果不需要單個單詞,則可以消除內部括號。

請注意,如果您只需提取子字符串,則不需要使用if。只需要if根據匹配採取條件操作。

另請注意,由於${BASH_REMATCH[0]}包含整個匹配項,因此與較長的正則表達式會有很大不同。

+0

是的,我編輯了一個錯字,忘了輸出。謝謝。是的myString不是一個數組。我最初做了一個,但發現它並不需要for循環。我搞砸了一下,最後使用read -a將數組設置爲一個變量。我不確定什麼聲明-p BASH_REMATCH會給我,除了列出什麼數組。 – 2012-07-19 21:04:31

+0

@ pn1dude:是的,例如,'declare -p BASH_REMATCH'只是在測試時轉儲數組內容的便捷方式。 – 2012-07-19 22:29:31

0

每@Dennis威廉姆森的文章中,我搞砸周圍,結束了以下內容:

myString="DO-BATCH BATCH-DO" 
pattern='(([[:alpha:]]*)-([[:alpha:]]*)) +(([[:alpha:]]*)-([[:alpha:]]*))' 

[[ $myString =~ $pattern ]] && { read -a myREMatch <<< ${BASH_REMATCH[@]}; } 

echo "\${myString} -> ${myString}" 
echo "\${#myREMatch[@]} -> ${#myREMatch[@]}" 

for ((i = 0; i < ${#myREMatch[@]}; i++)); do 
    echo "\${myREMatch[$i]} -> ${myREMatch[$i]}" 
done 

這工作,除了罰款的myString必須有2個數值在那裏。所以我發佈這個,因爲它有點有趣,我很樂意搞亂它。但要獲得這種更通用和地址配對組的任何量(即DO-批)我要去跟我原來的答覆的修改版本:

myString="DO-BATCH BATCH-DO" 
myRE="([[:alpha:]]*)-([[:alpha:]]*)" 

read -a myString <<< $myString 

for aString in ${myString[@]}; do 
    echo "\${aString} -> ${aString}" 
    if [[ ${aString} =~ ${myRE} ]]; then 
    echo "\${BASH_REMATCH[@]} -> ${BASH_REMATCH[@]}" 
    echo "\${#BASH_REMATCH[@]} -> ${#BASH_REMATCH[@]}" 
    for ((i = 0; i < ${#BASH_REMATCH[@]}; i++)); do 
     echo "\${BASH_REMATCH[$i]} -> ${BASH_REMATCH[$i]}" 
    done 
    fi 
done 

我也喜歡像多個匹配一個perlre但是這工作正常。通過去除內括號

myRE="([[:alpha:]]*-[[:alpha:]]*)" 

找到的話DO-BATCH更小(更簡潔)組:

0

雖然這是一歲多的問題(不接受的答案),可以在正則表達式可以簡化爲和BATCH-DO

它適合我在你18:10時間回答。 $ {BASH_REMATCH [0]}和$ {BASH_REMATCH [1]}導致找到2個單詞。

相關問題