使用 grep、sed、awk(或 cut)定位要删除的字符串

Targeting a string for deletion with grep, sed, awk (or cut)

我正在尝试解析一些日志以获取每行的用户代理和帐户 ID。我已经设法将用户代理和包含帐户 ID 的字符串全部拉到同一行。

下一步是从较长的字符串中提取帐户 ID。我认为这会相当简单,因为我知道字符串的开头并且有 / 斜杠作为分隔符,但用户代理也包含斜杠并且字段数量不同。

日志文件当前看起来类似于以下示例,但有成百上千行需要解析。幸运的是,我正在处理一个有大量 space 空闲空间的分区。


USER_AGENT_PART         ACCOUNT_ID_Part_/plus/path/to/stuff/they/access

some user agent/1.3     KnownString1_32d4-56e-009f98/some/stuff/here
user/agent              KnownString1_12d3-345e-4c534/more/stuff/here
User/Agent cURL/1.5.0   KnownString2_12d34e56/stuff/things/stuff/stuff
one/User Agent/2.0      KnownString1_12d3_456e_7g8/more/random/stuff/stuff

所以目标是保留用户代理部分和帐户 ID 部分,并将他们正在访问的内容的路径放在最后一个字符串中。但我不能使用 / 或 space 作为一般分隔符,因为许多用户代理的名称中都有 / 和不同数量的 space。

此外,不同类型的用户代理远不止我这里的这个小示例。根据日志的不同,有 25 到 50 种不同的类型。因此,以用户代理为目标并尝试排除它似乎不值得。

开始的合乎逻辑的方法似乎是将帐户 ID 的一部分作为已知字符串(KnownString1 或 KnownString2)并从那里获取所有内容(未知数字和带破折号的字母)直到第一个/ 该帐户字符串。

然后我将删除第一个 /(在帐户 ID 字符串中)以及之后的所有内容。我希望我需要分两次执行此操作以利用用户 ID 的两个已知部分。

这看起来很容易,但我就是想不通如何开始定位最后一个字符串。我什至没有一个接近工作的好例子,因为我不知道如何通过定界符定位最后一个字符串,而不在用户代理部分捕获相同的定界符。

有什么想法吗?

编辑:每一行都有一个帐户 ID,该 ID 以其中两个常见的 KnownString_ 中的一个开头,然后是一系列未知数字和破折号,直到到达第一个 /。所以我不需要在定位字符串之前搜索包含它的行。

Edit2:我原来的帐户 ID 示例没有反映数字中混有字母。

Edit3:感谢 oguz ismail 和 kesubagu 的回复,我能够使用 egrep 解决这个问题。看来我是想把事情弄得比原来更复杂。我还意识到我需要重新审视 grep,因为它的功能远远超过我通常使用它的功能。

这就是我最终使用的一次性完成的方法:

egrep -o ".+(KnownString1|KnownString2)_[^/]+" logfile > logfile2

您可以将 egrep-o 选项一起使用,它只会输出与提供的正则表达式匹配的部分,因此您可以这样做

cat test | egrep -o ".+(KnownString1|KnownString2)_[_0-9-]+"

test 文件包含您提供的输入,本例中的输出是

some user agent/1.3     KnownString1_324-56-00998
user/agent              KnownString1_123-345-4534
User/Agent cURL/1.5.0   KnownString2_123456
one/User Agent/2.0      KnownString1_123_456_78

使用grep

$ grep -o '.*KnownString[^/]*' file
some user agent/1.3     KnownString1_32d4-56e-009f98
user/agent              KnownString1_12d3-345e-4c534
User/Agent cURL/1.5.0   KnownString2_12d34e56
one/User Agent/2.0      KnownString1_12d3_456e_7g8

.* 匹配 KnownString 之前的所有内容,[^/]* 匹配 KnownString 之后的所有内容,直到第一个 /.