代码之家  ›  专栏  ›  技术社区  ›  kervin

如何将复杂的二进制Perl正则表达式转换为C或PowerShell?

  •  3
  • kervin  · 技术社区  · 15 年前

    此Perl二进制regex位于 http://www.w3.org/International/questions/qa-forms-utf-8.en.php 匹配没有UTF-8 BOM头的UTF-8文档:

    $field =~
    m/\A(
     [\x09\x0A\x0D\x20-\x7E]            # ASCII
     | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
     |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
     | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
     |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
     |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
     | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
     |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
    )*\z/x;
    

    我需要这个,因为我正在研究 PowerShell equivalent to 'grep -I' ,其中一部分涉及检测文本编码。

    但我该如何用C或PowerShell重写它呢?或者换句话说,在“.Net Regex”语法中?

    编辑: 找到这个 http://social.msdn.microsoft.com/Forums/en-US/regexp/thread/6a81be63-e6da-4156-a5bf-8b9782a1ac40 关于所有东西的同一个Regex的问题。简而言之,这似乎不能在.Net上完成,因为.Net不支持二进制正则表达式。

    4 回复  |  直到 7 年前
        1
  •  1
  •   kervin    15 年前
        2
  •  1
  •   JasonTrue    15 年前

    如果一个序列没有无效的UTF-8字符,则可以将其视为UTF-8,这种可能性相当大。因为regexp用于.Net中的文本,而不是字节数组,所以这里有一个非regexp的解决方案。就我个人而言,我更愿意将其用作回退机制(例如mycommand-autodetect),并提供允许用户指定编码的管道参数。

           string result=String.Empty;
            Encoding ae = Encoding.GetEncoding(
                  Encoding.UTF8.EncodingName,
                  new EncoderExceptionFallback(), 
                  new DecoderExceptionFallback());
            try {
                result=ae.GetString(mybytes);
            }
            catch (DecoderFallbackException e)
            {
                //revert to some sensible default. Maybe the Ansi Code page for this environment?
                // This will use the substitution fallback mechanism, which usually replaces unknown characters with question marks.
                result=Encoding.Default.GetString(mybytes);
            }
    

    如果可以与非托管代码交互,请研究IE附带的MLANG dll。它有其他编码自动检测方法,这些方法可能更有用。

        3
  •  1
  •   SLaks    15 年前

    试试这个:(我没有检查它是否正确匹配;你可以很容易地试穿它 LINQPad ).

    new Regex(@"
        ^(
        [\x09\x0A\x0D\x20-\x7E]            # ASCII
        | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
        |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
        |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
        |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
        | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
        |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
        )*$", RegexOptions.IgnorePatternWhitespace)
    

    编辑 :

    尝试使用ASCII读取文件 StreamReader ;那应该符合你的要求。(请注意,我实际上并没有尝试)

        4
  •  0
  •   SLaks    15 年前

    你到底想做什么?

    你应该能够使用 System.Text.Encoding 上课。