AWK支持的Regex for ipv4 CIDR表示法

soat7uwm  于 2023-10-22  发布在  其他
关注(0)|答案(4)|浏览(102)

我正在使用awk解析一些CIDR,我需要一些东西来匹配以下地址:160.0.0.0/24
但不是:160.0.0.0/24aaa57
因此,只有在有效的CIDR表示法的情况下,它才应该匹配。如果我理解正确的话,awk也没有/d等等。
下面是一个示例:

awk '$0 ~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\// {print $0}' somefile.txt
mwngjboj

mwngjboj1#

有效的CIDR不仅仅意味着四组由句点分隔的数字。有效的CIDR要求每个数字介于0255之间。此外,子网掩码必须介于/0/32之间。或者它可能根本不存在,这意味着/32
根据https://www.oreilly.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

会是一个很好的正则表达式来满足四个带点的八位字节。添加子网掩码将导致:

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/(?:3[0-2]|[0-2]?[0-9]))?\b

和示例输出:

sridhar@ganymede:~> cat ip-test.txt 
172.20.128.1
172.228.202.1/24
172.268.200.2/2444
138.22.2222/1
10.0.0.1/33
10.0.0.1/32
10.0.0/24
sridhar@ganymede:~> egrep -o '\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/(?:3[0-2]|[0-2]?[0-9]))?\b' ip-test.txt 
172.20.128.1
172.228.202.1/24
10.0.0.1
10.0.0.1/32
sridhar@ganymede:~>
wztqucjr

wztqucjr2#

一个awk解决方案,没有正则表达式:

awk -F "[./]" '
   function checkip() {
           return $1>=1 && $1<=255 && $2>=0 && $2<=255 && $3>=0 && $3<=255 && $4>=0 && $4<=255 && $5>=8 && $5<=32
   }
   { print $1,$2,$3,$4,$5,checkip() }
' input.txt

这将使用来自How to Calculate a CIDR的信息检查CIDR
现在你只需要根据自己的需要进行输出.

6mzjoqzu

6mzjoqzu3#

从问题和其他答案中搜索IP/掩码示例列表:

$ cat ip.txt
172.20.128.1
172.228.202.1/24
172.268.200.2/2444
138.22.2222/1
10.0.0.1/33
10.0.0.1/32
10.0.0/24
160.0.0.0/24aaa57
160.0.0.0/24
160.0.0.0/24e57
199.0.0.0/24/27

一个awk的想法:

awk '

function valid(v,a) { return (int(v)==v && v>=a[0] && v<=a[1] ? 1 : 0) }

BEGIN { FS="/"                                     # split input on "/"
        ip[0]=0; ip[1]=255                         # ip tuple range
        sm[0]=0; sm[1]=32                          # subnet mask range
      }
      { print "############", $0
        n=split($1,a,".")                          # split ip on "."
        if (NF>2 || n!=4) next                     # more than 2 "/"-delimited fields or ip tuple count !=4?
        for (i=1;i<=4;i++)                         # loop through ip tuples
            if (! valid(a[i],ip)) next             # validate each tuple
        if (NF==2 && ! valid($2,sm)) next          # validate the subnet mask (if provided)
      }
1                                                  # if we get here we have a valid ip(/mask) so print it
' ip.txt

这产生:

############ 172.20.128.1
172.20.128.1                            << valid
############ 172.228.202.1/24
172.228.202.1/24                        << valid
############ 172.268.200.2/2444
############ 138.22.2222/1
############ 10.0.0.1/33
############ 10.0.0.1/32
10.0.0.1/32                             << valid
############ 10.0.0/24
############ 160.0.0.0/24aaa57
############ 160.0.0.0/24
160.0.0.0/24                            << valid
############ 160.0.0.0/24e57
############ 199.0.0.0/24/27
alen0pnh

alen0pnh4#

如果我理解正确的话,awk也没有/d等等。
GNU AWK具有所谓的字符类,在用户指南的Bracket Expressions章节中有描述,设计用于[],例如,如果您需要在file.txt中查找包含字母后跟数字的行,您可以将其表示为

awk '/[[:alpha:]][[:digit:]]/' file.txt

160.0.0.0/24但不是:160.0.0.0/24aaa57
为了防止匹配部分而不是整个字提供Regexp operartos中描述的\y字边界,考虑以下简单示例,

24 xyz
24a yz
24ab z

然后

awk '/24\y/' file.txt

给出输出

24 xyz
  • (在GNU Awk 5.1.0中测试)*

因此,只有在有效的CIDR表示法的情况下,它才应该匹配。
考虑到它规定每个元素都在某个范围内,利用算术比较而不是正则表达式可能更直接。

相关问题