perl 如何在正则表达式中区分数字和ip地址?

ilmyapht  于 2023-02-19  发布在  Perl
关注(0)|答案(3)|浏览(109)

例如,如果我们查看5.56和183.55.0.144。基本上,当您执行类似/\d+\.\d+/这样的操作时,它匹配5.56、189.55和0.144。是否有一种方法可以通过regexp只匹配数字而不匹配IP地址的部分?我尝试使用lookaheads,但我不知道它应该是什么样的...
下面是我尝试的一组例子:
1.五点五六分<some_text> 5.56 <some_text>

  1. www.example.com<some_text> 183.55.0.144 <some_text>
  2. 454444555.6877878487874
    1.一点七五分。
    如何得到1,3和4,没有2的部分?
    我试过这样的方法:
  3. \d+\.\d+
  4. \d+\.\d(?!\.)
  5. (?<!\.)\d+\.\d+(非常接近...)
  6. (?<!\.)\d+\.\d(?!\.)
  7. (?!(?:[0-9]{1,3}\.){3}[0-9]{1,3})\d+\.\d+(?!\.)\d+(非常接近)
  8. \d+\.(?!(?:\.\d+){2})\d+
    1.还有很多不同的形式。
    Google给出了类似这样的信息:[-+]?[0-9]*\.?[0-9]+[+-]?[0-9]+[.][0-9]*([e][+-]?[0-9]+)?以及许多其他变体。但它们都是ip的匹配部分。
    另外,抱歉我的英语很差。
bkkx9g8r

bkkx9g8r1#

使用一个库来匹配/验证IP地址,从而丢弃这样的字符串,是一种可靠的方法。

/(?<!\.[0-9])(?<!\.) ([0-9]+)\.([0-9]+) (?![0-9]*\.[0-9])/x;

它可以像问题中所问的那样工作,并且可以用于我测试的许多其他案例。
有了评论中明确的需求,我们可以走“安全”的路:构建一个包含所有可能性的交替模式
在我的例子中,不需要像“.75”或“+50”这样的浮点数。
只是在示例中显示而已。
关于周围的符号。他们是文本,空格,句号结束或什么都没有。
首先,正则表达式本身

(?: ^ | [a-zA-Z\s] ) ([0-9]+)\.([0-9]+) (?: [a-zA-Z\s] | (?:\.(?:[^0-9]|$)) | $ )

在Perl程序中进行测试,并进行布局以便于阅读

use warnings;
use strict;
use feature 'say';

my @tt = (                # test strings from the question
    '<some_text> 5.56 <some_text>',
    '<some_text> 183.55.0.144 <some_text>',
    '4544445555.6877878487874',
    '1.75.'
);

push @tt, @ARGV;          # add strings if given on command line

for (@tt) {
    say "--- $_";                 # print current test-string
    say for                       # print captures, one per line
        m{ (?: ^ | [a-zA-Z\s] )   # beginning of string or letter/space
           ([0-9]+) \. ([0-9]+)   # decimal number as expected, nums captured 
           (?: [a-zA-Z\s]         # letter/space
               | (?: \.           #   or period followed by
                   (?: [^0-9]|$)) #      non-number or end-of-string
               | $ )              #   or end-of-string
         }xg;
}

# The other approach    
#for (@tt) {
#    say for /(?<!\.[0-9])(?<!\.) ([0-9]+)\.([0-9]+) (?![0-9]*\.[0-9])/xg;
#}

我用一个额外的测试字符串运行它,如

> perl prog.pl "a 0.23 is not .230 nor 12.23. But 22.33.44 is a-no"

然后打印出来

--- <some_text> 5.56 <some_text>
5
56
--- <some_text> 183.55.0.144 <some_text>
--- 4544445555.6877878487874
4544445555
6877878487874
--- 1.75.
1
75
--- a 0.23 is not .230 nor 12.23. But 22.33.44 is a-no
0
23
12
23

匹配的是来自问题的5.564544445555.68778784878741.75.和来自输入字符串的0.2312.23,其中包含每个浮点数的数字对被捕获和打印。
如果需要捕获浮动,则将([0-9]+)\.([0-9]+)更改为([0-9]+\.[0-9]+)

mi7gmzs6

mi7gmzs62#

@Andy Ray解答:[^\.0-9](\d+(\.\d+)?)[^\.0-9]在以下情况下匹配:
1.* * 5.56英镑**<some_text>5.56<some_text>

  1. www.example.com<some_text> 183.55.0.144 <some_text>
    1.* * 4544445555.6877878487874**
    1.一点七五分。
  2. www.example.com 127.0.0.1
    1.* * 555**(如果数字末尾没有内容,则不匹配)
    矿山:(?<!\.)(?:\d+\.)(?!\d+\.\d+)\d+
    1.* * 5.56英镑**<some_text>5.56<some_text>
  3. www.example.com<some_text> 183.55.0.144 <some_text>
    1.* * 4544445555.6877878487874**
    1.* * 1.75**。
  4. www.example.com 127.0.0.1
    1.五百五十五
    另一种方法是用一些神奇的替换来替换所有的IP地址,执行你的数字regex,然后将它们替换回(c)@AndyRay
7xllpg7q

7xllpg7q3#

示例数据的另一个选项可能是:

(?<!\S)\d+\.\d+\b(?!\.\d)
    • 说明**
  • (?<!\S)负向后看,向左Assert空白边界
  • \d+\.\d+\b匹配1+位数. 1+位数
  • (?!\.\d)负前瞻,Assertnot .,后跟一个向右的数字

参见regex101 demo

相关问题