【问题标题】:regular expression to select particular word when it is not followed by particular pattern?正则表达式在没有特定模式时选择特定单词?
【发布时间】:2020-05-17 10:44:52
【问题描述】:

我有一个这种格式的数据列表:

eth0: flags=73<UP,LOOPBACK,RUNNING>  mtu 1500
    inet 127.0.0.1  netmask 255.0.0.0
    inet6 ::1  prefixlen 128  scopeid 0xfe<compat,link,site,host>
    loop  (Local Loopback)
    RX packets 0  bytes 0 (0.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 0  bytes 0 (0.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=73<UP,LOOPBACK,RUNNING>  mtu 1500
    inet6 ::1  prefixlen 128  scopeid 0xfe<compat,link,site,host>
    loop  (Local Loopback)
    RX packets 0  bytes 0 (0.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 0  bytes 0 (0.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

我需要选择eth1(这是第一个单词,并且始终以e开头的单词)后面没有127.0.0.1(也可能出现在下一行的后面)。

这里eth0不合格,因为后面跟着127.0.0.1

我尝试了所有方法,但似乎没有任何效果。甚至可以使用正则表达式吗?如果是,那怎么办?

【问题讨论】:

  • 您对上述文本的预期输出是什么?您的平台是什么?
  • 我有上述数据的列表,我的预期输出看起来像[eth0, eth1, eth2] 等,平台是Linux ubuntu。

标签: regex ubuntu awk


【解决方案1】:
$ awk -v RS= -F':' '!/[[:space:]]127\.0\.0\.1[[:space:]]/{print $1}' file
eth1

这将在每个 UNIX 机器上的任何 shell 中使用任何 POSIX awk 来工作。

【讨论】:

    【解决方案2】:

    您可以使用 Ununtu 原生提供的 awk 命令:

    awk -F ': ' '$1 ~ /^e[[:alnum:]]+$/ && NF==2{s=$1; p=NR} 
           NR==p+1 && !/ 127\.0\.0\.1[[:blank:]]/{print s}'
    

    说明:

    -F ': '  # make ": " as input delimiter
    $1 ~ /^e[[:alnum:]]+$/ && NF==2 { # if $1 starts with e and has 1+ alphanumeric characters later and there are exactly 2 fields in that line
       s=$1      # save $1 in var s
       p=NR      # save record no in var p
    }
    NR==p+1 && !/ 127\.0\.0\.1[[:blank:]]/ { # we are processing (p+1)th record and it doesn't have " 127.0.0.1 " in it
       print s   # print s
    }
    

    【讨论】:

    • 但所选单词应始终以e 开头,之后的字母数可能超过:
    • 耶!它正在工作。你能给我解释一下吗?
    • awk 命令语法是 awk options 'selection _criteria {action }' 但我在您的代码中找不到这个结构?
    • 我在回答中添加了解释。
    【解决方案3】:

    不确定 Ubuntu 的实现细节,但您可以使用负前瞻:

    ^eth\d+(?=:)(?!.*\n.*[^0-9]127\.0\.0\.1[^0-9])
    
    • ^eth\d+(?=:) - 行首必须是“eth”,后跟一个或多个数字,后跟一个冒号,但不要捕获冒号
    • (?!.*\n.*[^0-9]127\.0\.0\.1[^0-9]) - 确保上一个匹配项后面的内容不包含“127.0.0.1”

    https://regex101.com/r/NeEAnn/1

    【讨论】:

    • @rahulKushwaha 永远不要使用(.|\n)*,这总是一个错误的想法。 .(通常)可以匹配换行符,前提是使用正则表达式模式传递正确的选项。
    • 我希望这将在 regex101 网站上运行良好,因为您似乎已经在那里测试过它,但它不适用于任何标准 UNIX 工具。我很惊讶 OP 接受它作为最佳答案。
    • @EdMorton 正则表达式风格和可用工具集在我回答时是未知的,我在开场白中提到了这一点。鼓励用户接受对他们帮助最大的答案。如果我的回答没有帮助他们实现目标,我们非常欢迎 OP 更改已接受的答案。
    • 对,您的回答没有任何问题。正如我所说,我确信它在 regex101 上会很好用,我只是很惊讶 OP 接受了它(因此有效地阻止其他人发布答案),因为它在任何标准 UNIX 工具(前瞻和@ 987654327@ 是问题),从评论来看,他们似乎仍在努力使用他们使用的任何工具使其工作。
    • 谢谢。不过,我认为他们的工具更有可能不支持前瞻,并将前瞻语法解释为其他内容(例如,( 可能被解释为捕获组的开始,? 被解释为零或 -一个重复,等等)恰好没有失败,并为一个示例用例产生预期的输出。但在不知道 OP 使用什么工具的情况下,我们都只是在猜测......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 2021-04-20
    • 1970-01-01
    相关资源
    最近更新 更多