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
Regex to match IP addresses
提问by mrbolichi
I am trying to match IP addresses found in the output of traceroute
by means of a regex. I'm not trying to validate them because it's safe enough to assume traceroute
is 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 -E
option to have grep
use the POSIX ERE flavor. Thus, grep
used 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 grep
the 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 -o
option with grep
: grep -oE 'ERE_pattern' file
/ grep -o 'BRE_pattern' file
.
要提取 IP使用-o
选项grep
:grep -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:
有关的: