我们正在从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
。结果将用于全文搜索,因此不区分大小写。
答案 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';
模式详细信息
\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)
说明:
(?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详细信息:
\b
:匹配单词边界(?:
:启动非捕获组
(?=(?:\pL\h+){3}\pL\b)
:先行断言我们有3个以上的单个字母,中间用1个以上的空格隔开|
:或(?<!^)\G
:\G
在上一场比赛的结尾声明位置。 (?<!^)
确保在第一次匹配时我们不匹配字符串的开头)
:结束非捕获组(\pL)
:匹配一个字母并将其捕获\h+
:后接1+个水平空格(?=\pL\b)
:声明我们前面只有一个字母$1
,这是我们捕获的空白的左侧字母