【问题标题】:Can regex match all the words outside quotation marks?正则表达式可以匹配引号外的所有单词吗?
【发布时间】:2014-09-23 20:02:55
【问题描述】:

我最近为我的 lit 课打了一篇文章,我的老师特别规定了一个字数限制,其中不包括文章中的引文。我想,为什么不制作一个为你计算的脚本呢?当然,我可以通过阅读整个文本并忽略引号内的单词来以无聊的方式做到这一点,但我觉得使用正则表达式和Array.count 有一种更简洁的方式。由于我对 Regex 几乎一无所知,有人可以帮助我/告诉我使用 Regex 是不可能的吗?

Tl;dr:使用 Regex 匹配文本中引号外的所有单词(或空格,无关紧要),并计算结果数组中的项目。

【问题讨论】:

  • 你的文字除了引号之外还有引号吗?
  • 引用是否可以转义或不平衡?
  • @Cratylus 不," 和 ' 中的所有文本都是引号。
  • @anubhava 不平衡,你的意思是不封闭吗?
  • 你为什么不写一个语言解析器,就像他们用于 C++ 的那些?

标签: regex language-agnostic match


【解决方案1】:

根据需要,可以使用The Greatest Regex Trick Ever

"[^"]*"|(\w+)

并计算第一个capture group的匹配。

\w+ 匹配一个或多个单词字符。

test at regex101.com


也跳过单引号字符串:

"[^"]*"|'[^']*'|(\w+)

test at regex101

【讨论】:

    【解决方案2】:

    这很容易使用 PCRE(当然也可以是 Perl):

    ".*?"(*SKIP)(?!)|(?<!\w)'.*?'(?!\w)(*SKIP)(?!)|[\w']+
    

    如果要处理多行引号,请使用g 修饰符和s

    Demo

    为了便于阅读,这里是x 版本:

      ".*?"              (*SKIP)(?!)
    | (?<!\w)'.*?'(?!\w) (*SKIP)(?!)
    | [\w]+
    

    第一部分将匹配 "' 引号内的所有内容并将其丢弃 ((*SKIP)(?!))。第二部分将匹配所有单词(在此示例中,我将' 作为单词的一部分包含在内)。 ' 字符将仅在单词的开头/结尾被视为引号边界,以便您使用诸如 isn't 之类的内容。

    可能的修改:

    • 要将文本 isn't 计为两个单词,请将 [\w']+ 替换为 \w+
    • 要将像 mother-in-law 这样的文本计为一个单词而不是 3 个单词,请将 [\w']+ 替换为 [-\w']+

    你明白了;)

    这是一个使用这个正则表达式的完整 Perl 脚本:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    $_ = do { local $/; <> };
    print scalar (() = /".*?"(*SKIP)(?!)|(?<!\w)'.*?'(?!\w)(*SKIP)(?!)|[\w']+/gs), "\n";
    

    执行它,传入一个文件或包含要计算字数的文本的 STDIN,它会在 STDOUT 上输出字数。

    【讨论】:

    • @Bluefire 该死的,是的,我会在一分钟内解决这个问题
    • 不,忽略我。刚刚意识到,如果考虑到 ',那么撇号也会考虑在内。
    • @Bluefire 给你,第二个版本好多了(它把 isn't 算作一个词)。如果要将 isn't 算作两个词,请将 [\w']+ 替换为 \w+
    【解决方案3】:

    一般的解决方案会非常困难,因为有些作品会有多段引号,其中第一段不会关闭引用,但第二段以引号开头。所以在文档范围内匹配引号会很困难。

    另一方面,您可以逐段进行,并为每个段落累积非引用字数。当然,仍然存在可能破坏这一点的病态案例(例如包含标点符号列表的段落,包括引号)。

    在 Perl 中,假设 getWordCount sub 存在于某处,并假设您以某种方式将文档拆分为称为 @paragraphs 的段落数组,这可能如下所示:

    my $wordCount = 0;
    foreach my $paragraph (@paragraphs) {
        $paragraph =~ s/\".*?\"/g; # remove all quotation marks which have a matching quotation mark
        $paragraph =~ s/\".*$/g; # remove quotation marks which go to the end of the paragraph
        $wordCount += getWordCount($paragraph);
    }
    print "There are $wordCount words outside of quotations, maybe!";
    

    【讨论】:

      【解决方案4】:

      这样会更好:

      字符总数 - 总和(引号内的字符)

      您可以使用此正则表达式查找所有“引用”字符串:\"[^"]*\"

      【讨论】:

        猜你喜欢
        • 2014-12-23
        • 1970-01-01
        • 1970-01-01
        • 2014-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多