bash 正则表达式匹配 IP 地址

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44654809/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 16:13:25  来源:igfitidea点击:

Regex to match IP addresses

regexbash

提问by mrbolichi

I am trying to match IP addresses found in the output of tracerouteby means of a regex. I'm not trying to validate them because it's safe enough to assume tracerouteis valid (i.e. is not outputting something like 999.999.999.999. I'm trying the following regex:

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

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

I'm testing it in regex101and it does validate an IP address. However, when I try

我正在regex101 中测试它,它确实验证了一个 IP 地址。但是,当我尝试

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

I get nothing. What am I missing?

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

回答by Wiktor Stribi?ew

You used a POSIX ERE pattern, but did not pass -Eoption to have grepuse the POSIX ERE flavor. Thus, grepused POSIX BRE instead, where you need to escape {n,m}quantifier and (...)to make them be parsed as special regex operators.

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

Note you need to escape a .so that it could only match a literal dot.

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

To make your pattern work with grepthe way you wanted you could use:

要使您的模式以grep您想要的方式工作,您可以使用:

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

See an online demo.

查看在线演示

However, this regex will also match a string of several digits because the .is optional.

但是,这个正则表达式也将匹配一个由多个数字组成的字符串,因为.是可选的。

You may solve it by unrolling the pattern as

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

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

See another demo.

请参阅另一个演示

Basically, it matches:

基本上,它匹配:

  • [0-9]{1,3}- 1 to 3 occurrences of any ASCII digit
  • (\.[0-9]{1,3}){3}- 3 occurrences of:
    • \.- a literal .
    • [0-9]{1,3}- 1 to 3 occurrences of any ASCII digit
  • [0-9]{1,3}- 任何 ASCII 数字出现 1 到 3 次
  • (\.[0-9]{1,3}){3}- 出现 3 次:
    • \.- 文字 .
    • [0-9]{1,3}- 任何 ASCII 数字出现 1 到 3 次

To make sure you only match valid IPs, you might want to use a more precise IP matching regex:

为确保只匹配有效 IP,您可能需要使用更精确的 IP 匹配正则表达式

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

See this online demo.

请参阅此在线演示

You may further tweak it with word boundaries (can be \</ \>or \b), etc.

您可以使用单词边界(可以是\</\>\b)等进一步调整它。

To extract the IPsuse -ooption with grep: grep -oE 'ERE_pattern' file/ grep -o 'BRE_pattern' file.

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

回答by codeforester

To make a more effective validation, it is better to use a function instead of a simple regex match:

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

#!/bin/bash
is_valid_ip() {
  local arr element
  IFS=. read -r -a arr <<< ""                  # 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
}

You can invoke this as:

您可以将其调用为:

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


Related:

有关的: