![如何 grep 与第一列匹配的字符串?](https://linux22.com/image/178923/%E5%A6%82%E4%BD%95%20grep%20%E4%B8%8E%E7%AC%AC%E4%B8%80%E5%88%97%E5%8C%B9%E9%85%8D%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%9F.png)
我试图仅获取匹配的字符串(match_E2
和pattern_2
)以及第一列。
abcd.corp;;a123,Virtual,aws,Linux,Linux,match_E2,Database
web1.corp;;,Virtual,azure,match_E2,Linux,corpo,Database
web2.corp;;match_E2,Virtual,a2responsible,Linux_Suse,Linux,corpo,Database
web3.corp;;Virtual,Virtual,corpo,pattern_2,Linux,corpo,Database
web4.corp;;Virtual,Virtual,corpo,,Linux,pattern_2,Database
预期产出可能低于
abcd.corp,match_E2
web1.corp,match_E2
web2.corp,match_E2
web3.corp,pattern_2
web4.corp,pattern_2
我尝试使用选项-o
ingrep
但它只给出匹配的字符串。
答案1
我敢说你的案子可能会更好地处理sed
。
对于match_E2
图案:
$ sed -nE 's/^([^;]+).*(match_E2).*/\1,\2/p' file.txt
对于pattern_2
图案:
$ sed -nE 's/^([^;]+).*(pattern_2).*/\1,\2/p' file.txt
对于这两种模式一次性:
$ sed -nE 's/^([^;]+).*(match_E2|pattern_2).*/\1,\2/p' file.txt
也就是说,基本上:
$ sed -nE 's/^([^;]+).*( ).*/\1,\2/p' file.txt
# ^ ^
# | |
# ---------------------
# put within these two parentheses the same (Extended Regular Expression) pattern you would use with `grep -E`
请注意,它仅依赖于至少一个;
作为第一个字段和行的其余部分之间的分隔符。
答案2
以下awk
命令应该执行您想要的操作:
awk -F'[;,]' -v pat="match_E2" '$0~pat{for (i=3;i<NF;i++) {if ($i ~ pat) printf("%s,%s\n",$1,$i)}}' file.txt
该
-F'[;,]'
选项将告知awk
将;
和识别,
为字段分隔符并相应地分割行。请注意,虽然 POSIX 标准要求将此类多字符字段分隔符解释为完整的正则表达式,但仍可能存在awk
无法正确实现此功能的版本。该模式通过以下方式传递给 awk
-v pat="match_E2"
该模式通过命令行选项请注意,这会将模式解释为完整的正则表达式。如果其中的字符在此上下文中具有特殊含义,则需要转义它们!如果当前行与模式匹配(
$0 ~ pat
意味着“如果整行与存储在pat
某处的正则表达式匹配”),它将循环遍历所有相关字段(字段 3 是最后一个字段之后的第一个字段;
)并识别实际匹配的字段(条件if ($i ~ pat)
)。然后它通过打印第一个字段 ($1
) 和匹配字段 ( )$i
printf()
。这假设匹配行上只能有一个这样的字段!
如果您寻找多种模式,您可以pat
相应地制定正则表达式,如下所示
awk -F'[;,]' -v pat="match_E2|pattern_2" ' ... etc ... '
或运行该命令两次,每个模式运行一次。
答案3
有点grep -o
像 awk 版本,使用以下match
函数:
$ awk -F';' 'match($0,/match_E2|pattern_2/) {print $1 "," substr($0,RSTART,RLENGTH)}' file
abcd.corp,match_E2
web1.corp,match_E2
web2.corp,match_E2
web3.corp,pattern_2
web4.corp,pattern_2
答案4
这会进行完整的文字字符串匹配,因此即使您的目标字符串包含正则表达式元字符或在输入中显示为子字符串,它也会起作用:
$ awk '
BEGIN { strs["match_E2"]; strs["pattern_2"]; FS=";"; OFS="," }
{ for (str in strs) if (index(","$NF",",","str",")) print $1, str }
' file
abcd.corp,match_E2
web1.corp,match_E2
web2.corp,match_E2
web3.corp,pattern_2
web4.corp,pattern_2
有关部分匹配与完全匹配的示例,请考虑以下输入:
$ cat file
abcd.corp;;a123,Virtual,aws,Linux,Linux,mismatch_E2,Database
web1.corp;;,Virtual,azure,match_E2,Linux,corpo,Database
web2.corp;;match_E2,Virtual,a2responsible,Linux_Suse,Linux,corpo,Database
web3.corp;;Virtual,Virtual,corpo,pattern_275,Linux,corpo,Database
web4.corp;;Virtual,Virtual,corpo,,Linux,pattern_2,Database
请注意,现在输入的第一行包含mismatch_E2
而不是match_E2
,第四行是pattern_275
而不是pattern_2
。现在运行上面的 awk 脚本,看看它是否产生了预期的输出:
$ awk '
BEGIN { strs["match_E2"]; strs["pattern_2"]; FS=";"; OFS="," }
{ for (str in strs) if (index(","$NF",",","str",")) print $1, str }
' file
web1.corp,match_E2
web2.corp,match_E2
web4.corp,pattern_2
对于正则表达式与字符串匹配的示例,请将输入中的match_E2
第 1 行更改为 ,m.*2
将patch_2
第 4 行更改为:p.*2
$ cat file
abcd.corp;;a123,Virtual,aws,Linux,Linux,m.*2,Database
web1.corp;;,Virtual,azure,m.*2,Linux,corpo,Database
web2.corp;;m.*2,Virtual,a2responsible,Linux_Suse,Linux,corpo,Database
web3.corp;;Virtual,Virtual,corpo,pattern_2,Linux,corpo,Database
web4.corp;;Virtual,Virtual,corpo,,Linux,pattern_2,Database
并修改上面的 awk 脚本以查找m.*2
andp.*2
而不是match_E2
andpattern_2
并再次看到它产生了预期的输出:
$ awk '
BEGIN { strs["m.*2"]; strs["p.*2"]; FS=";"; OFS="," }
{ for (str in strs) if (index(","$NF",",","str",")) print $1, str }
' file
abcd.corp,m.*2
web3.corp,p.*2