2017-09-25 119 views
1

我有一個字符串,它是這樣的格式:猛砸正則表達式捕獲組

"Mike H<[email protected]>" [email protected] "Mike H<[email protected]>" 

如果我寫的JS,C#等正常的正則表達式,我會做這個

(?:"(.+?)"|'(.+?)'|(\S+)) 

並重復匹配組以獲取每個字符串,理想情況下不帶引號。我最終想每個值添加到一個數組,所以在本例中,我會在陣列中結束了3項如下:

Mike H<[email protected]> 
[email protected] 
Mike H<[email protected]> 

我不能找出如何與grep複製這一功能或sed或bash正則表達式。我試着像

echo "$email" | grep -oP "\"\K(.+?)(?=\")|'\K(.+?)(?=')|(\S+)" 

一些事情這樣做的問題是,雖然拍攝組的它種模仿功能,它並沒有真正與倍數工作,所以我得到捕獲像

"Mike 
H<[email protected]>" 
[email protected] 

如果我刪除了前面/後面的邏輯,我至少得到3個字符串,但第一個和最後一個仍然用引號括起來。在這種方法中,我將輸出輸出到read,這樣我就可以將每個字符串單獨添加到數組中,但我可以使用其他選項。

編輯:

我想我輸入例如可能是混亂的,它只是一個可能的輸入。實際輸入可以是任何數量的任何順序的雙引號,單引號或不引號(不帶空格)的字符串。我提供的Javascript/C#正則表達式是我試圖實現的真正行爲。

+0

請發佈所需的輸出。 – CWLiu

+0

問題已更新爲所需的輸出。 – hakenmt

+1

作爲一個約定,不要使用大寫字母作爲Bash變量,並且在引號中引用它們。 – dawg

回答

0

我能做到這一點有什麼工作,但不是儘量精簡我想要的代碼是:

arr=() 
while read line; do 
    line="${line//\"/}" 
    arr+=("${line//\'/}") 
done < <(echo $email | grep -oP "\"(.+?)\"|'(.+?)'|(\S+)") 

這g爲我提供了一個捕獲組的數組,並以任何順序處理輸入,如果它沒有空格,可以用雙引號或單引號包裝,或者根本沒有。它還提供了數組中沒有包裝引號的元素。感謝所有的建議。

0

您可以使用sed實現這一目標,

$ sed -r 's/"(.*)" (.*)"(.*)"/\1\n\2\n\3/g' <<< "$EMAIL" 
Mike H<[email protected]> 
[email protected] 
Mike H<[email protected]> 
+0

這個工作,如果我知道輸入格式;我提供的僅僅是一個可能的輸入的代表,實際上它是一個輸入字符串,它是空格分隔的字符串,可以或不可以用雙引號或單引號將其包含在引用字符串中的空格內。 (還是)感謝你的建議。 – hakenmt

2

您可以使用Perl:

$ email='"Mike H<[email protected]>" [email protected] "Mike H<[email protected]>"' 
$ echo "$email" | perl -lane 'while (/"([^"]+)"|(\S+)/g) {print $1 ? $1 : $2}' 
Mike H<[email protected]> 
[email protected] 
Mike H<[email protected]> 

或者純猛砸,它變得有點羅嗦:

re='\"([^\"]+)\"[[:space:]]*|([^[:space:]]+)[[:space:]]*' 
while [[ $email =~ $re ]]; do 
    echo ${BASH_REMATCH[1]}${BASH_REMATCH[2]} 
    i=${#BASH_REMATCH} 
    email=${email:i} 
done 
# same output 
+1

很酷(+1)。 ...或者打印$ 1 || $ 2' – JJoao

0

修改您正則表達式是這樣的:

grep -oP '("?\s*)\K.*?(?=")' file 

輸出:

Mike H<[email protected]> 
[email protected] 
Mike H<[email protected]> 
+0

該模式假定輸入始終按該順序;輸入應該是可能的輸入模式的代表,該輸入模式是包含空格分隔的字符串的輸入字符串,其可以包含或不包含在單引號或雙引號中以處理字符串內的空白。 – hakenmt

1

你的第一個表現是好的;只要小心引號(當存在\時使用單引號)。在最後修剪"與sed。

$ echo $mail | grep -Po '".*?"|\S+' | sed -r 's/"$|^"//g' 
Mike H<[email protected]> 
[email protected] 
Mike H<[email protected]> 
+1

這個答案的問題在於,它將輸入字符串中的雙引號和單引號作爲輸出的一部分進行捕獲,但在引用用法中進行了說明。 – hakenmt

+0

@hakenmt,謝謝你的評論:我的壞。我添加了一個額外的步驟,以適應要求,但解決方案不是很優雅... – JJoao

1

GAWK + 的bash溶液(添加每個項目陣列):

email_str='"Mike H<[email protected]>" [email protected] "Mike H<[email protected]>"' 

readarray -t email_arr < <(awk -v FPAT="[^\"'[:space:]]+[^\"']+[^\"'[:space:]]+" \ 
         '{ for(i=1;i<=NF;i++) print $i }' <<<$email_str) 

現在,所有的項目都在email_arr

訪問第二項:

echo "${email_arr[1]}" 
[email protected] 

訪問第3項:

echo "${email_arr[3]}" 
Mike H<[email protected]> 
+0

這對我來說是實現正在尋找的正則表達式行爲和數組結果的工作。 – hakenmt

+0

@hakenmt,這很好 – RomanPerekhrest

0

使用GNU AWK和FPATdefine fields by content

$ awk ' 
BEGIN { FPAT="([^ ]*)|(\"[^\"]*\")" } # define a field to be space-separated or in quotes 
{ 
    for(i=1;i<=NF;i++) {    # iterate every field 
     gsub(/^\"|\"$/,"",$i)   # remove leading and trailing quotes 
     print $i      # output 
    } 
}' file 
Mike H<[email protected]> 
[email protected] 
Mike H<[email protected]> 
+0

這個版本沒有考慮單引號字符串,如果我在最後一個引號字符串(出於某種原因)之後有一個尾部空格,它會添加一個空白條目。這也不會將它們添加到數組中,但可以輕鬆更新以進行此操作。我認爲@ RomanPerekhrest的這個版本更接近。 – hakenmt