【问题标题】:grep command line in Windows PowerShell to count IP adresses在 Windows PowerShell 中使用 grep 命令行来计算 IP 地址
【发布时间】:2019-07-28 07:03:41
【问题描述】:

目前我在 Linux 上使用这个命令:

grep Ban /var/log/fail2ban.log | grep -v 'Restore Ban' | sed 's/\s\s*/ /g' | cut -d" " -f8 | sort | uniq -c | sort -t ' ' -n -b

日志文件如下所示:

2019-03-04 07:14:45,778 fail2ban.filter [19052]: INFO [sshd] 找到 2*8.1*7.1*9.2*9 2019-03-04 07:14:46,412 fail2ban.actions [19052]:通知 [sshd] Ban 2*8.1*7.1*9.2*9 2019-03-04 07:15:04,708 fail2ban.actions [19052]:通知 [sshd] Unban 1*9.2*.2*4.1*6 ...

输出如下:

8 1*2.2*6.1*1.1*5 12 3*.1*.*4.*6 18 1*5.2*8.2*5.4 19 1*2.2*6.1*1.1*4 72 3*.1*6.2*.9*

我已经用Get-Content 试过了,但我不明白所有的 PowerShell 语法。

【问题讨论】:

  • 如果您不了解某些 cmdlet,您可以随时使用Get-Help Get-Content -Full。您可以阅读Select-String 的帮助。
  • 请去查找 PowerShell 教程。 SO 既不是免费翻译服务,也不是让您熟悉所用语言的基础知识的替代品。

标签: linux powershell grep command


【解决方案1】:

您的 Linux 命令将许多功能打包到一个管道中。
尽管您自己没有努力解决问题,构造一个等效的 PowerShell 命令是一个比较有趣的练习 带有 PowerShell 解决方案的 Unix 实用程序解决方案

为了设置场景,让我解释一下你的命令是做什么的:

  • grep Ban /var/log/fail2ban.log 区分大小写查找文件/var/log/fail2ban.log 中包含单词Ban 的行并仅传递这些行。

  • grep -v 'Restore Ban' 进一步(区分大小写)过滤掉 (-v) 包含短语“Restore Ban”的行。

  • sed 's/\s\s*/ /g' 替换 1 个或多个空白字符的所有 (g) 运行。 (\s; 在现代正则表达式方言中,您将使用 \s+) 和 单个空格 ...

  • ... 然后,cut -d" " -f8 可以可靠地从生成的以空格分隔的列表(例如,2*8.1*7.1*9.2*9)的每一行中提取第 8 个字段。

  • sort 然后对结果行进行词法排序,uniq -c 剔除重复项,同时在每个唯一行前面加上 count 个重复项 (-c),@987654344 @ 表示唯一的行。

  • 最后,sort -t ' ' -n -b 按重复计数数字对结果行进行排序。

简而言之:您的命令通过正则表达式匹配过滤日志文件,从每行中提取第 8 个字段,消除重复项,并打印以重复计数为前缀的唯一字段,按重复计数升序排序。


下面是一个近似等效的 PowerShell 命令,它:

  • 更具可读性(因此,必然更冗长)

  • 涉及的步骤更少

  • 最终提供了更大的灵活性,原因是:

    • 通过管道发送 对象,而不仅仅是必须经常(重新)解析的 文本 - 正是这一特性构成了 PowerShell 从传统 shell 的进化飞跃。
    • 可轻松编入管道的语言功能(与 bash 等类似 POSIX 的 shell 相比)要出色得多。

也就是说,你为增加功率付出的代价是性能

  • 直接比较的命令使用 Unix 实用程序执行得更好,尽管 PowerShell cmdlet 提供的通常更高级别的抽象和灵活性可能会弥补这一点。

这是命令,大致在 cmets 中对应的 Unix 实用程序调用:

Select-String -CaseSensitive '(?<!Restore )Ban' /var/log/fail2ban.log | #grep,grep -v
  ForEach-Object { (-split $_.Line)[7] } | # sed, cut -f8
    Group-Object | # uniq -c 
      Select-Object Count, Name | # construction of output *objects*
        Sort-Object Count, Name # sort, sort -n

该命令输出带有.Count(重复计数)和.Name 属性(日志文件中的第8 个字段)的objects,其中:

  • 允许进行稳健的额外处理(无需解析文本输出)。
  • 以友好的方式呈现给控制台(见下文)。

示例输出:

Count Name
----- ----
    8 1*2.2*6.1*1.1*5
   12 3*.1*.*4.*6
   18 1*5.2*8.2*5.4
   19 1*2.2*6.1*1.1*4
   72 3*.1*6.2*.9*

有关命令的解释,请参阅以下帮助主题,这些主题也可在本地通过Get-Help cmdletGet-Help cmdlet 获取,作为 PowerShell 安装的一部分:

【讨论】:

    【解决方案2】:
    ((Get-Content "fail2ban.log") -cmatch "(?<!Restore )Ban" | Select-String -Pattern "[0-9.*]+$" -AllMatches).matches.value | Group-Object | foreach {"$($_.count) $($_.name)"}
    

    这里的Get-Content 是抓取fail2ban.log 文件的每一行。 -cmatch 运算符正在执行区分大小写的正则表达式匹配。正则表达式模式在字符串 Restore 后面查找带有否定外观的字符串 Ban。 Select-String 在每行的末尾寻找一个正则表达式模式,该模式包含集合中的字符 (0123456789.*)。 matches.value 属性仅输出正则表达式中匹配的字符串。 Group-Object 将每个相同匹配的值分组为属性名称,并添加一个计数属性。由于 OP 正在捕获计数,我决定使用 Group-Object 来轻松获得它。 foreach 只是简单地进行格式化以匹配 OP 的输出表示。

    【讨论】:

    • 我添加了一些信息。我的意图是提供一个单一的班轮,可以根据他的数据集提供相同的输出。我没有尝试提供与海报提供的每个 Linux 命令相同的 PowerShell。因此,如果这就是 OP 想要的,那么我的答案并不是最好的。如果数据一致并且您喜欢正则表达式,我的答案是另一种方法。
    • 我仍然感谢您的回答。我会自己研究这些命令。但是我不想学习powershell,我只需要这个命令。所以谢谢你的帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 2012-04-09
    • 1970-01-01
    • 2015-08-19
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多