如果兩個匹配字串中的任何一個匹配,如何提取行?

如果兩個匹配字串中的任何一個匹配,如何提取行?

我有一個文件,其中有幾行包含國家/地區名稱的信息,如下所示。

$cat country.txt

max_china_clean_foo
man_india_raw_bar
max_us_clean_bax
max_uk_raw_bar
max_canada_raw_foo
max_au_clean_bar

我只想從此文件中提取國家/地區名稱。我目前正在使用下面的程式碼在 for 循環中提取國家/地區名稱

val=${val#*_}
val=${val%_clean*}
echo $val

但產生的輸出只有china, usau國家/地區名稱,因此我必須重複類似的程式碼並進行少量修改才能提取其餘國家/地區,如下所示

val=${val#*_}
val=${val%_raw*}
echo $val

clean我知道,這不是一種清晰的編碼方式,因此需要您的幫助從所有包含或raw字串的行中提取國家/地區名稱。

有沒有辦法使用 awk 或 sed 提取具有兩個匹配鍵的所有國家/地區名稱?我的輸出應該是這樣的

china
india
us
uk
canada
au

答案1

我不會使用 shell 循環來處理文本

在這裡,你可以這樣做:

cut -d _ -f 2 < country.txt

或者,如果輸入可能包含沒有_字元的行:

awk -F _ 'NF >= 2 {print $2}' < country.txt

如果國家/地區名稱可能包含_字符,並且您希望返回該行的第一次_出現和第一次出現之間_raw_clean之後的部分,您可以執行以下操作:

perl -ne 'print $1 if s/^[^_]*_(.*?)_(clean|raw)/' < country.txt

或使用 GNU grep

grep -Po '^[^_]*_\K.*?(?=_clean|_raw)' < country.txt

-P(前提是已grep使用 PCRE 支援建構),正規表示式是與 perl 相容的正規表示式。在這些正規表示式中,\K重置匹配字串的開頭,並且(?=...)是一個前瞻運算符,也就是說,它會查找字串的其餘部分是否匹配...,而該部分是否包含在匹配部分中。-o使grep輸出匹配的部分,因此這裡它打印與.*?上面匹配的內容,這是 的非貪婪等價物.*,即0 個或多個字符的序列,盡可能短,在本例中遵循0 個或多個下劃線的序列([^_]*) 位於行 ( ) 的開頭,^後面跟著下劃線,並假設其後跟_raw_clean

有了pcregrep,你還可以這樣寫:

pcregrep -o1 '^[^_]*_(.*?)_(clean|raw)'

使用-o1,它會列印與第一個 相符的部分(...)

答案2

這是 awk 風格的方式

awk -F'_' '/clean|raw/{ print $2}'

相關內容