【问题标题】:Java Regex vs. PHP, Dangling meta character '?'Java 正则表达式与 PHP,悬空元字符“?”
【发布时间】:2020-10-12 02:40:01
【问题描述】:

即使这是一个 Java 问题,我也会用 PHP 来标记它。正则表达式是从 PHP 源复制的,所以我希望一些 PHPers 可以帮助解决这个问题。

我决定构建一个简单的垃圾邮件过滤器,只是为了好玩,我从 MediaWiki 复制了垃圾邮件阻止列表:https://meta.wikimedia.org/wiki/Spam_blacklist

大多数情况下这似乎可行,但有一些模式因语法错误而失败。我不知道这是拼写错误还是 PHP 使用的语法与 Java 不同。谁能帮我修复这些正则表达式以便它们编译?

问题如下:

java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 17
\bfacebo(?:o[ob]|?o)k\.com\b
                 ^
java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 5
\b????\.tk\b
     ^
java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 0
??\.xsl\.pt\b
^
java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 4
\b????\.shop\b
    ^
java.util.regex.PatternSyntaxException: Dangling meta character '?' near index 4
\b???\.??\b
    ^

这是编译它们的代码,以防您感兴趣。不过我不认为这有什么不同。

   private static synchronized void init() throws IOException {
      
      if( blackListPatterns.get() != null ) return;
      InputStream blacklistfile = SpamBlackList.class.getResourceAsStream( "blacklist.txt" );
      BufferedReader buf = new BufferedReader( new InputStreamReader( blacklistfile, "UTF-8" ) );
      ArrayList<String> blacklist = new ArrayList<>( 12000 );
      for( String line; (line = buf.readLine()) != null; )
         if( !line.isBlank() && line.trim().charAt(0) != '#' )
            blacklist.add( line );
      ArrayList<Pattern> tempPatterns = new ArrayList<>( blacklist.size() );
      for( String pat : blacklist )
         try {
            tempPatterns.add( Pattern.compile( pat ) );
         } catch ( java.util.regex.PatternSyntaxException ex ) {
            System.err.println( ex );  // should log this, low level like FINER
         }
      blackListPatterns = new WeakReference<>( tempPatterns );
   }
   
   private static volatile WeakReference<List<Pattern>> 
           blackListPatterns = new WeakReference( null );

【问题讨论】:

  • 请告诉我们您的正则表达式模式应该匹配什么。似乎 Java 的正则表达式引擎无法弄清楚应该应用什么?
  • 是的,正如我提到的,我从其他地方复制了正则表达式,所以我实际上并不知道。例如,第一个似乎与垃圾邮件站点相匹配,它们在“facebook.com”的“book”部分添加了额外的“o”或“b”,但由于我不知道 PHP 正则表达式,我不确定是什么额外的? 可能正在尝试匹配(如果是拼写错误,可能什么都没有)。这基本上是我的问题:这是试图匹配什么?
  • 问这个问题的另一种方式可能是:是否 ? 在 PHP 中实际上意味着什么,如果是这样,那又是什么呢?还是打错字了?
  • 根据this demo,您当前的正则表达式模式在 PHP 中 not 有效。
  • 啊,好吧,这可能就是答案。这是一个错字。

标签: java php regex


【解决方案1】:

您下载的 https://meta.wikimedia.org/wiki/Spam_blacklist (blacklist.txt) 副本已损坏。悬空的问号是非 ASCII 字符,例如\bfacebo(?:o[ob]|?o)k\.com\b 实际上是 \bfacebo(?:o[ob]|ıo)k\.com\b。请注意无点的“ı”。

下载https://meta.wikimedia.org/wiki/Spam_blacklist?action=raw并注意它是UTF-8。

您可能希望将 Unicode 标志传递给正则表达式。还要考虑到:

这里所说的正则表达式并不是真正的正则表达式,而是插入到硬编码正则表达式中的子模式。即上面的子模式 Foo 将创建一个像 /^Foo$/usi 这样的正则表达式。

(见https://www.mediawiki.org/wiki/Extension:TitleBlacklist#Block_list)。

【讨论】:

  • 出色的侦探工作,我没想过要检查。在我检查这个的时候给我一点时间。编辑:是的,它排序了。该文件以某种方式损坏,或者我的 IDE 切换了我的编码。现在解析行没有错误。
猜你喜欢
  • 2014-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多