【问题标题】:Find Unclosed Quotes (‘- or “-Style)查找未封闭的引号('- 或 “- 样式)
【发布时间】:2014-07-23 21:14:22
【问题描述】:

我正在直接从 OCR 引擎编辑一些文本,在某些段落中,OCR 引擎会忽略开始和结束引号。我更喜欢在 HTML 模式下进行编辑,因此最终会得到一些文本,例如:

<p>“Wait a moment,” Jacey said. The street light lit up his aged, rat face. Who’s on the move?”</p>

请注意缺少的“

另外一句话:

<p>“He said he’ coming afer you,” Harry said, and he’ bringing the boys too!”</p>

我使用这个正则表达式:([>\.\,])(.*?)”,它似乎对第二句话起作用,但对第一句话不起作用。这是因为正则表达式是从左到右匹配的,因此匹配了不应在引号内的额外句子 The street light lit up his aged, rat face.。 我在想如果从右到左进行匹配,问题就可以解决。我知道这是 C# 中可用的一个选项,但我正在使用基于文本的编辑器的正则表达式引擎来编辑一个简单的文本文件。有没有办法只定位“之前的最后一句,也就是Who’s on the move?

[编辑] 我一直在尝试使用lookbehind regex:(?<=(?:\. |, |>)(\w)(.*?))(”),它似乎找到了所有缺少开引号的句子“,但问题是我无法用\3“\1\2\3替换(?<=)构造中的内容,因为lookbehind是0长度。相反,文本只是重复。例如,使用上面的正则表达式,句子Who’s on the move?” 变为Who’s on the move?”“Who’s on the move?”

任何想法都会受到赞赏。 谢谢

【问题讨论】:

  • 这是一个有趣的问题,因为"quotes 'can be "nested"'" 很快就会看。
  • 其实你的例子很复杂!!
  • 是的,但是“你'必须'允许嵌套”:)

标签: regex


【解决方案1】:

递归和定义子程序

以下正则表达式检查字符串是否平衡。下面的代码(参见the online demo 中的输出)检查了几个字符串。解释在 cmets 中。

$balanced_string_regex = "~(?sx)                  # Free-Spacing
(?(DEFINE)            # Define a few subroutines
   (?<double>&ldquo;(?:(?!&[lr]squo;).)*&rdquo;)  # full set of doubles (no quotes inside)
   (?<single>&lsquo;(?:(?!&[lr]dquo;).)*&rsquo;)  # full set of singles (no quotes inside)
   (?<notquotes>(?:(?!&[lr][sd]quo;).)*)          # chars that are not quotes
)                     # end DEFINE

^                       # Start of string
(?:                     # Start non-capture group
   (?&notquotes)        # Any non-quote chars
   &l(?<type>[sd])quo;  # Opening quote, capture single or double type
   # any full singles, doubles, not quotes or recursion
   (?:(?&single)|(?&double)|(?&notquotes)|(?R))*
   &r\k<type>quo;       # Closing quote of the correct type
   (?&notquotes)      # 
)++                   # Repeat non-capture group
$                     # End of string
~";

$string = "&ldquo;He said  &rdquo; &lsquo;He said  &rsquo;";
check_string($string);
$string = "<p>&ldquo;Wait a moment,&rdquo; Jacey said. The street light lit up his aged, rat face. Who&rsquo;s on the move?&rdquo;</p>";
check_string($string);
$string = "<p>&ldquo;Wait a moment,&rdquo; Jacey said. The street light lit up his aged, rat face. &lsquo;Whos on the &ldquo;move?&rdquo; &rsquo;</p>";
check_string($string);
$string = "<p>&ldquo;He said he&rsquo; coming afer you,&rdquo; Harry said, and he&rsquo; bringing the boys too!&rdquo;</p>";
check_string($string);
$string = "<p>&ldquo;He &lsquo;said he&rsquo; coming afer you,&rdquo; Harry said, and he&ldquo; bringing the boys too!&rdquo;</p>";
check_string($string);


function check_string($string) {
    global $balanced_string_regex;
    echo (preg_match($balanced_string_regex, $string)) ?
        "Balanced!\n" :
        " Nah... Not Balanced.\n" ;
}

输出

Balanced!
 Nah... Not Balanced.
Balanced!
 Nah... Not Balanced.
Balanced!

替换缺少的引号

正如我在 cmets 中指出的那样,IMO 替换缺失的引号是危险的:缺失的引号应该落在哪个词之前或之后?如果有任何类型的嵌套,我们能否确定我们已经正确识别了缺失的报价?出于这个原因,如果你要做任何事情,我倾向于匹配平衡部分(希望它是正确的)并删除任何额外的引号。

上面的模式适用于各种调整。例如,在this regex demo 上,我们匹配并替换了一个不平衡的引用。既然有人要求这样做,我将不情愿地提供第二个可能的调整——this one 在不匹配的右引号之前的短语开头插入一个缺失的左引号。

【讨论】:

  • 谢谢。这仅检查是否没有互补的左括号或右括号。它不会尝试提供合适的位置来放置缺失的报价。我想我必须让自己更清楚。在编辑过程中,为了找到所有丢失的引号,我首先将所有正确引用的语句转换为“。这就是我所做的:搜索:([&gt;\s])\&amp;ldquo\;(.*?[^\s])\&amp;rdquo\;([&lt;\s]) 替换:\1"\2"\3 剩下的是那些带有两个引号之一的语句但不是两者兼而有之。修正右引号很容易,因为我可以从右到左搜索。
  • This only checks 你真有趣。这是一个非常复杂的正则表达式。找到一个合适的位置是我们现在的一个小调整,我稍后再看。
  • 嘿,兄弟,如果它对你不起作用,你不必接受答案——在那个阶段,当人们发现答案很丰富时,会使用复选标记上方的“向上”箭头(它赞成)。我建议这样做直到您满意为止(您可以不接受),然后在您满意时接受。会看插入问题。 :)
  • 下一个问题:你想如何平衡不平衡的报价?我可以关闭它:&amp;lquo;&amp;rquo; 或直接删除它。猜测头寸是非常危险的 IMO,收盘价可能在任何地方。
  • 我已经在我的原始帖子中添加了一些新信息。我想要的是选择结束引号之前的最后一句话。 (?&lt;=(?:\. |, |&gt;)(\w)(.*?))(&amp;rdquo;) 会做到的。唯一的问题是无法替换lookbehind 组中的内容。
猜你喜欢
  • 2011-10-09
  • 2016-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多