正则表达式能否匹配引号之外的所有单词?

4
我最近为我的文学课写了一篇文章,我的老师明确规定了一个单词限制,不包括引用。我想,为什么不写一个脚本来计算呢?当然,我可以通过阅读整个文本并忽略引号内的单词来完成这项工作,但我觉得使用正则表达式和Array.count会更简洁。由于我对正则表达式知之甚少,有人可以帮助我吗/告诉我是否可以使用正则表达式实现? 简而言之:使用正则表达式匹配文本中所有在引号外的单词(或空格,无所谓),并计算结果数组中的项目数。

除了引用之外,您的文本中是否有任何引号? - Cratylus
1
引号是否可以被转义或不平衡? - anubhava
@Cratylus 不,所有在双引号和单引号内的文本都是引用。 - Bluefire
@anubhava,你的意思是未关闭吗? - Bluefire
@Bluefire 是的,没错。 - anubhava
1
为什么不编写一个语言解析器,就像他们用于C++一样? - user557597
4个回答

7

2
一般的解决方案可能会很困难,因为有些作品将包含多段引用,第一段没有闭合引号,而第二段以引号开头。 因此,在整个文档范围内匹配引号会很难。
另一方面,您可以逐段进行,并累计每个段落的非引用字数。 当然,仍然会有一些特殊情况可能会破坏这种方法(例如一个段落包含标点符号列表,包括引号)。
在Perl中,假设某个getWordCount子程序存在于某个地方,并且假设您已经将文档分割成名为@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!";

2

使用 PCRE (或者 Perl) 很容易实现:

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

使用g修饰符,并在处理多行引用时使用s

演示

这里是可读性更强的x版本:

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

第一部分将匹配引号 "' 之间的所有内容并将其丢弃((*SKIP)(?!))。第二部分将匹配所有单词(在此示例中,我已包括 ' 作为单词的一部分)。' 字符仅在单词的开头/结尾处被视为引号边界,以便您可以使用像 isn't 这样的东西。
可能的修改:
  • 要将文本 isn't 视为两个单词,请将 [\w']+ 替换为 \w+
  • 要将类似于 mother-in-law 的文本视为一个单词而不是三个单词,请将 [\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 好的,我马上处理。 - Lucas Trzesniewski
不好意思,忽然意识到如果考虑 ' ,那么撇号也会被计算在内。 - Bluefire
@Bluefire,这是第二个版本,它更好(它不会将“isn't”视为一个单词)。如果您想将“isn't”视为两个单词,请使用\w+替换[\w']+ - Lucas Trzesniewski

1

这样做会更好:

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

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


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