我有一个文件,其中有几行包含国家/地区名称的信息,如下所示。
$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
在这里,你可以这样做:
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}'