如何使用preg_replace删除过多的单个空格

时间:2018-10-03 16:51:22

标签: php regex preg-replace

我们正在从PDF文件中提取文本,并且出现包含畸形文本的结果的频率很高。专门在单词的字符之间添加空格。例如if (foo != null && !int.TryParse(foo?.Score, out _)) 作为foo != null返回。

SEATTLE个单字符“单词”的情况下,是否存在preg_replace的RegEx表达式可以删除任何空格?具体来说,要从出现的超过3个单个字母字符的字符串中删除空格,并用空格分隔吗?

如果用谷歌搜索了一段时间,但是甚至无法想象如何构造表达式。如评论中所述,我不希望所有空格都删除,而仅当出现> 3个单个字母字符时,例如S E A T T L E应该成为n。结果将用于全文搜索,因此不区分大小写。

3 个答案:

答案 0 :(得分:2)

您可以对preg_replace_callback使用简单的方法。匹配匿名函数中的'~\b[A-Za-z](?: [A-Za-z]){2,}\b~'str_replace空格:

$regex = '~\b[A-Za-z](?: [A-Za-z]){2,}\b~';
$result = preg_replace_callback($regex, function($m) {
     return str_replace(" ", "", $m[0]);
}, $s);

请参见regex demo

要仅匹配大写字母序列,请从模式中删除a-z

$regex = '~\b[A-Z](?: [A-Z]){2,}\b~';

还有另一件事:可能有软/硬空间,制表符以及其他类型的空白。然后,使用

$regex = '~\b[A-Za-z](?:\h[A-Za-z]){2,}\b~u';
                        ^^                ^

最后,要匹配任何Unicode字母,请使用\p{L}(仅匹配大写字母\p{Lu})而不是[a-zA-Z]

$regex = '~\b\p{L}(?:\h\p{L}){2,}\b~u';

注意:在某些情况下(例如,当有一个字母的单词时。您将不得不单独/手动处理这些情况。无论如何,没有安全的仅使用正则表达式的方法可以解决OCR问题。

模式详细信息

  • \b-单词边界
  • [A-Za-z]-一个字母
  • (?: [A-Za-z]){2,}-出现2次或以上
    • -一个空格(\h匹配任何一种水平空白)
    • [A-Za-z]-一个字母
  • \b-单词边界

使用u修饰符时,\h可以识别Unicode。

答案 1 :(得分:2)

您可以一口气做到这一点:

(?i:(?<!\S)([a-z]) +((?1))|\G(?!\A) +((?1))\b)

请参见live demo here

说明:

(?i: # Start of non-capturing group with case-insensitive modifier on
    (?<!\S) # Negative lookbehind to ensure there is no leading non-whitespace character
    ([a-z]) + # Capture one letter and at least one space
    ((?1)) # Capture one letter in 2nd capturing group
    | # Or
    \G(?!\A) + # Start match from where previous match ends 
               # with matching spaces
    ((?1))\b # Match a letter at word boundary
) # End of non-capturing group

PHP代码:

$str = preg_replace('~(?i:(?<!\S)([a-z]) +((?1))|\G(?!\A) +((?1))\b)~', '$1$2$3', $str);

答案 2 :(得分:1)

您可以将这种纯正则表达式方法与环顾四周和\G一起使用:

$re = '~\b(?:(?=(?:\pL\h+){3}\pL\b)|(?<!^)\G)(\pL)\h+(?=\pL\b)~';

$repl = preg_replace($re, '$1', $str);

RegEx Demo

RegEx详细信息:

  • \b:匹配单词边界
  • (?::启动非捕获组
    • (?=(?:\pL\h+){3}\pL\b):先行断言我们有3个以上的单个字母,中间用1个以上的空格隔开
    • |:或
    • (?<!^)\G\G在上一场比赛的结尾声明位置。 (?<!^)确保在第一次匹配时我们不匹配字符串的开头
  • ):结束非捕获组
  • (\pL):匹配一个字母并将其捕获
  • \h+:后接1+个水平空格
  • (?=\pL\b):声明我们前面只有一个字母
  • 替换中,我们使用$1,这是我们捕获的空白的左侧字母