【问题标题】:Extracing IP addresses as whole words with POSIX BRE/ERE regex使用 POSIX BRE/ERE 正则表达式将 IP 地址提取为整个单词
【发布时间】:2017-11-23 02:25:34
【问题描述】:

我正在尝试通过正则表达式匹配在 traceroute 的输出中找到的 IP 地址。我不想验证它们,因为假设traceroute 是有效的(即不输出类似999.999.999.999 的东西是足够安全的。我正在尝试以下正则表达式:

([0-9]{1,3}.?){4}

我正在regex101 中对其进行测试,它确实验证了 IP 地址。但是,当我尝试

echo '192.168.1.1 foobar' | grep '([0-9]{1,3}.?){4}' 

我什么也得不到。我错过了什么?

【问题讨论】:

  • 如果你使用grep -E '([0-9]{1,3}\.?){4}'?您使用了 POSIX ERE 模式,但没有通过 -E 选项。因此,grep 使用了 POSIX BRE。
  • @WiktorStribiżew 这行得通。愿意详细说明答案以便我接受吗?我也想看看如何使用 BRE 解决我的问题
  • 我没有注意到评论,但实际上我正在处理此更新,以展示如何在此处使用 BRE 语法。
  • 只是我的意见,但既然你知道你正在寻找一个 IP,那么简单的东西就像 \b\d{1,3}\.\d{1,3}\.\d{1, 3}\.\d{1,3}\b 可以解决问题。制作\.? optional 意味着 1234 将是一个有效的 IP 匹配。或者即使没有 \b 也可能没问题。
  • 请注意,How do you extract IP addresses from files using a regex in a linux shell? 帖子没有有效的 POSIX BRE/ERE 解决方案用于 IP 地址作为使用 grep 提取的全字。

标签: regex bash


【解决方案1】:

您使用了 POSIX ERE 模式,但没有通过 -E 选项让 grep 使用 POSIX ERE 风格。因此,grep 改用 POSIX BRE,您需要转义 {n,m} 量词和 (...) 以使它们被解析为特殊的正则表达式运算符。

请注意,您需要转义 .,以便它只能匹配文字点。

要使您的模式以您希望的方式与grep 一起使用:

grep -E '([0-9]{1,3}\.?){4}'      # POSIX ERE
grep '\([0-9]\{1,3\}\.\?\)\{4\}'  # POSIX BRE version of the same regex

查看online demo

然而,这个正则表达式也会匹配一个多位数字的字符串,因为. 是可选的。

你可以通过展开模式来解决它

grep -E '[0-9]{1,3}(\.[0-9]{1,3}){3}'      # POSIX ERE
grep '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}' # POSIX BRE

another demo

基本上,它匹配:

  • [0-9]{1,3} - 任何 ASCII 数字出现 1 到 3 次
  • (\.[0-9]{1,3}){3} - 出现 3 次:
    • \. - 文字 .
    • [0-9]{1,3} - 任何 ASCII 数字出现 1 到 3 次

为确保只匹配有效 IP,您可能需要使用 more precise IP matching regex

grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}\b' # POSIX ERE

this online demo

您可以进一步调整字边界(可以是\< / \>\b)等

要提取 IP,请使用 -o 选项和 grepgrep -oE 'ERE_pattern' file / grep -o 'BRE_pattern' file

【讨论】:

  • 那个正则表达式wont work。请改用this
  • @Olian04:我明白你的意思,我刚刚将 OP 正则表达式翻译成 POSIX BRE/ERE。已编辑。
  • @Olian04 或者更短一点:([0-9]{1,3}\.){3}[0-9]{1,3}。不过,这并不能捕获损坏的 IP 地址(例如 256.256.256.256)。
  • @VictorZamanian 您可能想要使用more precise IP matching regex 答案只是指出了如何修复当前的 OP 方法。匹配 IP 的方法有很多,而这一切都取决于用例。
【解决方案2】:

为了进行更有效的验证,最好使用函数而不是简单的正则表达式匹配:

#!/bin/bash
is_valid_ip() {
  local arr element
  IFS=. read -r -a arr <<< "$1"                  # convert ip string to array
  [[ ${#arr[@]} != 4 ]] && return 1              # doesn't have four parts
  for element in "${arr[@]}"; do
    [[ $element =~ ^[0-9]+$ ]]       || return 1 # non numeric characters found
    [[ $element =~ ^0[1-9]+$ ]]      || return 1 # 0 not allowed in leading position if followed by other digits, to prevent it from being interpreted as on octal number
    ((element < 0 || element > 255)) && return 1 # number out of range
  done
  return 0
}

你可以这样调用它:

while read -r ip; do
  is_valid_ip "$ip" && printf '%s\n' "$ip" 
done < <(your command that extracts ip address like strings)

相关:

【讨论】:

  • 尽管 OP 明确声明正则表达式验证就足够了,但这是一个很棒的小功能!
猜你喜欢
  • 2016-03-15
  • 1970-01-01
  • 2022-12-05
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 2011-06-20
相关资源
最近更新 更多