在匹配模式后仅返回一行的部分

问题描述 投票:-1回答:2

我需要帮助来处理一个命令,它是一个*(星)分隔文件有多行,如下所述。我想搜索以NM1*IL开头并提取最后一列的行。以下是显示的示例。

$ cat temp.txt
NM1*IL*1*RESTAR*FRENNY*M***MI*99358358~
N3*2164 Boeing Avenue~
N4*NEW DELHI*CA*94114~
DMG*D0*19550610*F~
NM1*PR*2*KFHP*****PI*94135~
NM1*IL*1*STAR*FRENY*M***MI*99358958~
NM1*IL*1*RESTA*ANNIE*M***MI*993583589~

我想要输出如下

99358358
99358958
993583589
linux shell unix
2个回答
0
投票

grep 'NM1[*]IL' temp.txt | awk -F'*' '{print $NF}' | sed 's/~$//'

您可以运行此管道的一部分(最多但不包括|)以查看特定命令对您的输入执行的操作。

grep 'NM1[*]IL' - 过滤输入行,以便只留下与此模式匹配的输入行。 grep将正则表达式作为其参数,*是一个特殊的正则表达式字符(表示它所遵循的符号的0或更多),因此它需要转义。我在这里使用了一个角色类([]),因为我觉得它很整洁。可以使用NM1\*IL达到同样的效果。

awk -F'*' - -F指定字段分隔符,我将其设置为*。 Awk将每个输入行拆分为字段,因此两个*s之间的任何内容都是awk的字段。

'{print $NF}'是它现在将在其输入上执行的awk程序。它说“对于所有输入行打印带有数字NF的字段”,其中NF是一个特殊的awk变量,它代表“字段数”。所以它的作用是打印最后一个字段。

sed 's/~$//' - 只是剥离落后的~$意味着行尾。所以这个sed用空字符串替换EOL之前的任何tildas。可以写tr -d '~',但这个sed更精确(只在EOL之前剥离tildas)。

grep(1)awk(1p)sed(1)都是标准的UNIX命令行实用程序。研究手册页以获取有关如何使用它们的更多信息。


0
投票

由于您的问题被标记为linux,我假设您使用的是GNU grep:

$ grep -oP '^NM1\*IL.*\*\K.*(?=~)' /tmp/file
99358358
99358958
993583589

这是使用带有后视和前瞻零宽度断言的pcre语法 - 当使用\K选项时,匹配到(?=...)-o内部的东西将不会包含在输出中。

© www.soinside.com 2019 - 2024. All rights reserved.