如果两个匹配字符串中的任何一个匹配,如何提取行?

如果两个匹配字符串中的任何一个匹配,如何提取行?

我有一个文件,其中有几行包含国家/地区名称的信息,如下所示。

$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, us/au地区名称,因此我必须重复类似的代码并进行少量修改才能提取其余国家/地区,如下所示

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}'

相关内容