【问题标题】:Remove multiple patterns of a file删除文件的多个模式
【发布时间】:2021-12-28 06:56:17
【问题描述】:

我有以下文件,我们称之为user.txt

2020/06/30 22:02:58 > [+] VALID USERNAME:   admin@spookysec.local
2020/06/30 22:03:58 > [+] VALID USERNAME:   admin-svc@spookysec.local
2020/06/30 22:04:58 > [+] VALID USERNAME:   backup@spookysec.local
2020/06/30 22:05:58 > [+] VALID USERNAME:   harry@spookysec.local
2020/06/30 22:06:58 > [+] VALID USERNAME:   wrgwrsd@spookysec.local
2020/06/30 22:07:58 > [+] VALID USERNAME:   brssdb@spookysec.local
2020/06/30 22:09:58 > [+] VALID USERNAME:   a@spookysec.local
2020/06/30 22:10:58 > [+] VALID USERNAME:   adm@spookysec.local
2020/06/30 22:11:58 > [+] VALID USERNAME:   admifdfdsn@spookysec.local

我想删除每一行的多个模式,只获取每行一个用户名的用户名(例如 admin、admin-sv)。 我尝试了两个单独的 sed,效果很好,

sed -r 's/.{16}$//' user.txt > user2.txt

然后

sed -r 's/.{42}//' user2.txt > user3.txt

但我认为有一种更快更性感的方式来做到这一点。

尤其是这个命令

sed -r 's/(@\D+)$//' user.txt > user2.txt

不起作用。我想删除@和以后的每个字符...

有没有人知道我做错了什么以及可能的解决方案?如果我可以使用 sed 或 grep 达到我的目标,那将是最好的。

【问题讨论】:

    标签: awk sed grep


    【解决方案1】:

    你可以试试这个sed:

    sed -E 's/.*[[:blank:]]|@.*//g' file
    
    admin
    admin-svc
    backup
    harry
    wrgwrsd
    brssdb
    a
    adm
    admifdfdsn
    

    说明:

    • .*[[:blank:]]: 匹配任何 0 个或多个字符后跟一个空格的字符串
    • |:或者
    • @.*:匹配 @ 以及之后的所有内容

    【讨论】:

    • 这是一个很好的答案。它适用于 Microsoft 和 Unix 文本文件(CRLF 与 LF 行结束),因为 [[:blank:] 与回车符 (CR) 不匹配,而 [[:space:]] 匹配。
    • 是的,非常感谢您的回答,尤其是您对命令组件的描述
    【解决方案2】:

    使用您显示的示例,请尝试以下代码。

    第一个解决方案:使用awk,这可以通过更简单的方式完成,请尝试关注一次。

    awk -F'VALID USERNAME:[[:space:]]+|@' '{print $2}' Input_file
    

    解释:在这里使用awk 编程。将VALID USERNAME:[[:space:]]+|@ 作为整个 Input_file 的字段分隔符,并根据要求打印每行的第二个字段。



    第二个解决方案:使用 GNU grep 请尝试以下操作。

    grep -oP 'VALID USERNAME:[[:space:]]+\K[^@]*' Input_file
    

    解释: 使用 GNU grep-oP 选项,其中 -o 仅打印匹配值,-P 启用 PCRE 正则表达式。在grep 的主程序中匹配VALID USERNAME:[[:space:]]+ 正则表达式,后跟\K(它将忘记以前匹配的值以便不打印它们),然后匹配@ 之前的所有内容以根据OP 显示的示例获取实际用户名.

    【讨论】:

      【解决方案3】:

      另一个使用 sed 和捕获组的变体,在替换中使用组 1 \1

      sed -E 's/.*[[:blank:]]([^@[:blank:]]+)@.*/\1/' file
      
      • .*[[:blank:]] 匹配到最后一个空格
      • ([^@[:blank:]]+) 在第 1 组中捕获匹配除 @ 或空格之外的 1+ 个字符
      • @.* 匹配 @ 和该行的其余部分

      输出

      admin
      admin-svc
      backup
      harry
      wrgwrsd
      brssdb
      a
      adm
      admifdfdsn
      

      另一个使用 awk 的选项,您可以在 @ 上拆分最后一列

      如果拆分返回了 2 个部分,则可以打印第一部分:

      awk '{
          nr=split($(NF), a, "@")
          if (nr==2) print a[1]
      }' file
      

      【讨论】:

        【解决方案4】:

        我会使用:

        sed 's/.*[[:space:]]\([^[:space:]]\)/\1/; s/@.*//'
        

        这与 anubhava 的(好)答案之间的细微差别在于,如果行尾有杂散的空白,它仍然有效。

        可能是不必要的/偏执的,但根据情况,我喜欢允许这样的事情。

        如果列不同,您可以使用:

        sed -E 's/(.*VALID[[:space:]]+USERNAME:[[:space:]]+)([^@[:space:]]+)(.*)/\2/'
        

        这匹配VALID USERNAME: 行中的任何位置,并打印下一个字段,直到但不包括第一个@ 或空白字符。您也可以将模式更改为 USERNAME: 或类似名称,具体取决于您的数据。

        最后,如果找不到@(即电子邮件字段为空或无效),这些变体会跳过一行:

        sed -n 's/.*[[:blank:]]\([^[:space:]]\)/\1/; s/@.*//p'
        sed -En 's/(.*VALID[[:space:]]+USERNAME:[[:space:]]+)([^@]+)(@.*)/\2/p'
        

        【讨论】:

          【解决方案5】:

          这可能对你有用(GNU sed):

          sed -nE 's/.*\<([^@]*)@.*/\1/p' file
          

          捕获并打印最后一个 @ 字符之前的单词。

          【讨论】:

            猜你喜欢
            • 2017-02-20
            • 1970-01-01
            • 1970-01-01
            • 2012-09-27
            • 2018-12-29
            • 2021-11-24
            • 2014-01-06
            • 2020-09-05
            • 1970-01-01
            相关资源
            最近更新 更多