2

我已经看到了在正则表达式中查找字符缺失的示例,我正在尝试在正则表达式中查找单词的缺失(可能使用否定的lookbehind)。

我有这样的代码行:

示例一:

protected static readonly string BACKGROUND_MUSIC_NAME = "Music_Mission_Complete_Loop_audio";

这是另一个:

mainWindow.Id = "MainWindow";

最后一张:

mainStoLabel.Text = "#stb_entry_clah";

我想通过查找所有像这样的字符串来仅捕获中间一个,a.) 在引号之间的实际字符串中前面没有“#”,并且 b.) 前面根本没有“readonly”这个词”。

我目前的正则表达式是这样的:

.*\W\=\W"[^#].*"

它捕获了前两个示例。现在我只想缩小上面的例子。如何捕获(不是字符)整个单词的缺失。

谢谢。

4

4 回答 4

2

我不完全理解你的问题,消极的前瞻看起来像这样:

(?!.*readonly)(?:.*\s\=\s"[^#].*")

如果字符串中没有单词“readonly”,则第一部分将匹配。

您使用哪种语言?

你想匹配什么,只有第二个例子,我理解正确吗?

于 2011-04-09T22:24:22.010 回答
2

你的否定前瞻断言中的错误是你没有把它放在一起以适应一般情况。当您向前爬行时,您需要使其断言适用于每个字符位置。它仅适用于您编写的一种可能的点,而您需要将其应用于所有点。请参阅下文,了解如何正确执行此操作。

这是一个工作演示,显示了两种不同的方法:

  1. 第一个使用负前瞻来确保左侧部分不包含只读且右侧部分不以数字符号开头。

  2. 第二个执行一个更简单的解析器,然后分别检查左侧和右侧的适用于每个约束的各个约束。

演示语言是 Perl,但相同的模式和逻辑几乎可以在任何地方使用。

#!/usr/bin/perl

while (<DATA>) {
    chomp;
#
# First demo: use a complicated regex to get desired part only
#
    my($label) = m{
        ^                           # start at the beginning
        (?:                         # noncapture group:
            (?! \b readonly \b )    #   no "readonly" here
            .                       #   now advance one character
        ) +                         # repeated 1 or more times
        \s* = \s*                   # skip an equals sign w/optional spaces
        " ( [^#"] [^"]* ) "         # capture #1: quote-delimited text
                                    #   BUT whose first char isn't a "#"
    }x;

    if (defined $label) {
        print "Demo One: found label <$label> at line $.\n";
    }
#
# Second demo: This time use simpler patterns, several
#
    my($lhs, $rhs) = m{
        ^                       # from the start of line
        ( [^=]+ )               # capture #1: 1 or more non-equals chars
        \s* = \s*               # skip an equals sign w/optional spaces
        " ( [^"]+ ) "           # capture #2: all quote-delimited text
    }x;

    unless ($lhs =~ /\b readonly \b/x || $rhs =~ /^#/) {
        print "Demo Two: found label <$rhs> at line $.\n";
    }

}
__END__
protected static readonly string BACKGROUND_MUSIC_NAME = "Music_Mission_Complete_Loop_audio";
mainWindow.Id = "MainWindow";
mainStoLabel.Text = "#stb_entry_clah";

我有两点建议。首先是确保您始终使用/x模式,以便您可以生成文档化和可维护的正则表达式。第二个是像第二种解决方案那样一次做一些事情而不是像第一种那样一次做所有事情要干净得多。

于 2011-04-10T20:12:16.313 回答
1

^[^"=]*(?<!(^|\s)readonly\s.*)\s*=\s*"[^#].*"似乎符合您的需求:

  • 第一个等号之前的所有内容都不应包含readonly或引用
  • readonly不是用单词边界而是用空格识别的(行首除外)
  • 等号可以被任意空格包围
  • 等号后面必须跟一个带引号的字符串
  • 引用的字符串不应以#

如果您只需要字符串或带引号的字符串,则可以使用环视或捕获组。

注意:根据您自己的正则表达式,这会丢弃最后一个引号之后的任何内容(与您的示例中的分号不匹配)

于 2011-04-09T23:20:16.617 回答
0

您绝对需要指定语言。消极的前瞻/后瞻是你需要的。

查看此站点以了解如何在Delphi、GNU (Linux)、Groovy、Java、JavaScript、.NET、PCRE (C/C++)、Perl、PHP、POSIX、PowerShell、Python、R、REALbasic、 Ruby、Tcl、VBScript、Visual Basic 6、wxWidgets、XML Schema、XQuery 和 XPath

于 2011-04-09T22:31:43.713 回答