如何忽略URL中的正则表达式部分?

3
在我的一个PHP站点上,我使用这个正则表达式自动从字符串中删除电话号码: $text = preg_replace('/\+?[0-9][0-9()-\s+]{4,20}[0-9]/', '[removed]', $text); 但是,当用户发布包含多个数字作为其文本的长URL时,URL也会受到preg_replace的影响,从而导致URL破坏。
如何确保上述preg_replace不会改变$text中包含的URL?
编辑: 按要求,这里有一个被preg_replace破坏的URL示例:
$text = 'Please help me with my question here: https://dev59.com/bnrZa4cB1Zd3GeqP0UOP  Thanks!';
$text = preg_replace('/\+?[0-9][0-9()-\s+]{4,20}[0-9]/', '[removed]', $text);
echo $text; 

//echoes: Please help me with my question here: https://stackoverflow.com/questions/[removed]/ Thanks!

只需检查有问题的文本是否以“http”开头即可。 - nietonfir
@nietonfir:但如果URL在文本中间呢? - ProgrammerGirl
请提供几个包含电话号码的URL示例,并说明它们是如何被分解的。 - user4035
@user4035:请查看我上面的编辑。 - ProgrammerGirl
@ProgrammerGirl- 发布了一个关于如何做到这一点的答案。 - user557597
显示剩余2条评论
3个回答

2

我认为您需要解析URL和电话号码,例如/(?: url \K | phone number)/ - sln

@sln:那我该怎么做呢?如果有帮助的话,这里有一个URL正则表达式:stackoverflow.com/a/8234912/869849 - ProgrammerGirl

以下是使用提供的URL和电话号码正则表达式的示例:

Php测试用例:

 $text = 'Please help me with my +44-83848-1234 question here: http://stackoverflow.com/+44-83848-1234questions/20589314/ phone #:+44-83848-1234-Thanks!';
 $str = preg_replace_callback('~((?:(?:[a-zA-Z]{3,9}:(?://)?)(?:[;:&=+$,\w-]+@)?[a-zA-Z0-9.-]+|(?:www\.|[;:&=+$,\w-]+@)[a-zA-Z0-9.-]+)(?:(?:/[+\~%/.\w-]*)?\??[+=&;%@.\w-]*\#?\w*)?)|(\+?[0-9][0-9()\s+-]{4,20}[0-9])~',
                   function( $matches ){
                        if ( $matches[1] != "" ) {
                             return $matches[1];
                        }
                        return '[removed]';
                   },
                   $text);

 print $str;

输出 >>

 Please help me with my [removed] question here: http://stackoverflow.com/+44-83848-1234questions/20589314/ phone #:[removed]-Thanks!

使用 RegexFormat 处理的正则表达式

 # '~((?:(?:[a-zA-Z]{3,9}:(?://)?)(?:[;:&=+$,\w-]+@)?[a-zA-Z0-9.-]+|(?:www\.|[;:&=+$,\w-]+@)[a-zA-Z0-9.-]+)(?:(?:/[+\~%/.\w-]*)?\??[+=&;%@.\w-]*\#?\w*)?)|(\+?[0-9][0-9()\s+-]{4,20}[0-9])~'

     (                                  # (1 start), URL
          (?:
               (?:
                    [a-zA-Z]{3,9} :
                    (?: // )?
               )
               (?: [;:&=+$,\w-]+ @ )?
               [a-zA-Z0-9.-]+ 
            |  
               (?: www \. | [;:&=+$,\w-]+ @ )
               [a-zA-Z0-9.-]+ 
          )
          (?:
               (?: / [+~%/.\w-]* )?
               \??
               [+=&;%@.\w-]* 
               \#?
               \w* 
          )?
     )                                  # (1 end)
  |  
     (                                  # (2 start), Phone Num
          \+? 
          [0-9] 
          [0-9()\s+-]{4,20} 
          [0-9] 
     )                                  # (2 end)

非常有趣,谢谢!有没有一行 preg_replace 的方法可以实现这个? - ProgrammerGirl
不需要用一行 preg_replace_callback 吗?这取决于替换的内容是什么。正如我之前所说的,用 preg_replace /(?: url \K | phone number)/ 替换为 ""。 - user557597
我尝试了你在评论中提到的方法,它可以正确地忽略URL,但是它会在URL末尾添加"[removed]"。你知道如何解决这个问题吗? - ProgrammerGirl
这里有一个困境。如果你用空字符串替换,可以使用简单的 preg_replace 来完成。URL 必须被独立处理以便通过它,因为电话号码是它的子集。在这种情况下,没有实际的方法来使用断言。在正则表达式引擎内部,回调是一个简单的额外函数调用,实际上是不可感知的开销。如果你想完成工作,我建议使用这种方法。 - user557597

1

你应该多写一些代码,而不是在那里摸着自己的头,这样你会更加自信满满!

<?php
    $text = "This is my number20558789yes with no spaces
    and this is yours 254785961
    But this 20558474 is within http://stackoverflow.com/questions/20558474/
    So I don't remove it
    and this is another url https://dev59.com/bnrZa4cB1Zd3GeqP0UOP 
    Thanks!";
    $up = "(https?://[-.a-zA-Z0-9]+\.[a-zA-Z]{2,3}/\S*)"; // to catch urls
    $np = "(\+?[0-9][0-9()-\s+]{4,20}[0-9])"; // you know this pattern already
    preg_match_all("#{$up}|{$np}#", $text, $matches); // match all above patterns together ($matches[1] contains urls, $matches[2] contains numbers)
    preg_match_all("#{$np}#", print_r(array_filter($matches[1]), true), $urls_numbers); // extract numbers from urls, actually if we have any
    $diff = array_diff(array_filter($matches[2]), $urls_numbers[0]); // an array with numbers that we should replace
    $text = str_replace($diff, "[removed]", $text); // replacing
    echo $text; // here you are

然后输出为:
This is my number[removed]yes with no spaces
and this is yours [removed]
But this 20558474 is within http://stackoverflow.com/questions/20558474/
So I don't remove it
and this is another url https://dev59.com/bnrZa4cB1Zd3GeqP0UOP 
Thanks!

0

可以假设电话号码通常前面有空格或在行首,这样可以防止您意外更改URL,因为URL中间不会存在空格或换行符:

$text = preg_replace('/(^|\s)\+?[0-9][0-9()-\s+]{4,20}[0-9]/', '[removed]', $text);

你的解决方案存在问题,因为只需在电话号码前面加上一个字母,就可以轻松(甚至是无意地)规避它。理想情况下,我正在寻找一种解决方案,如果数字序列出现在URL内部,则仅忽略正则表达式,但我不知道如何做到这一点。 - ProgrammerGirl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接