【问题标题】:Targeting a string for deletion with grep, sed, awk (or cut)使用 grep、sed、awk(或 cut)定位要删除的字符串
【发布时间】:2019-10-20 13:07:50
【问题描述】:

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

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

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


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 部分,并将他们正在访问的内容的路径放在最后一个字符串中。但我不能使用 / 或空格作为通用分隔符,因为许多用户代理的名称中有 / 和不同数量的空格。

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

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

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

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

有什么想法吗?

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

Edit2:我最初的帐户 ID 示例并未反映数字中混有字母。

Edit3:感谢 oguz ismail 和 kesubagu 的回复,我能够使用 egrep 解决这个问题。看起来我试图让事情变得比原来更复杂。我还意识到我需要重新审视 grep,因为它的功能远远超出了我倾向于使用它的用途。

这是我最终使用的,一次性使用:

egrep -o ".+(KnownString1|KnownString2)_[^/]+" 日志文件 > 日志文件2

【问题讨论】:

  • 第一个字段,例如^................ KnownString...(直到KnownString...的开头是固定宽度吗?
  • 感谢您的回复。不,不幸的是,第一个字段长度不是固定长度。但是我能够将 kesubagu 和 oguz ismail 的响应混合成一个一次性完成的响应。

标签: awk sed grep cut


【解决方案1】:

您可以将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

【讨论】:

  • 哇。首先非常感谢您的回复。这让我更加接近。它确实按照我指定的方式工作。不幸的是,我忽略了数字中也有一些字母的事实。我将编辑原始帖子以反映这一点。因此,即使它接近了,它也不能完全像我的真实世界案例那样工作。希望我可以以此为起点并对其进行调整以使其正常工作。我整天都在 awk 和 sed 教程之间跳来跳去,寻找可行的方法。我想还有很多东西要学。明天会尝试调整它。
【解决方案2】:

使用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 之后的所有内容,直到第一个/

【讨论】:

    猜你喜欢
    • 2020-05-15
    • 2013-03-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多