我一直在努力解决我希望用正则表达式解决的问题。
假设我有一个字符串,可以包含任何字母数字,并且子字符串可能被方括号包围。这些子字符串可以像这样出现在字符串中的任何位置。也可以有任意数量的括号子串。
示例:
你可以看到一些括号中的子串中有空格,这很好。我现在的主要问题是当我在括号外面遇到空格时:
现在我想保留括号内的空格,但在其他地方删除它们。
对于像
这样的字符串来说,这会变得有点棘手在这里,我希望返回:
我现在花了一些时间阅读关于外观,消极断言等的不同注册页面,这让我头晕目眩。
注意:对于访问此内容的任何人,我都没有寻找任何涉及嵌套括号的解决方案。如果是这种情况,我可能会像下面提到的一些评论一样务实地做。
答案 0 :(得分:11)
这个正则表达式可以解决这个问题:
[ ](?=[^\]]*?(?:\[|$))
只需替换与“”匹配的空格。
基本上它所做的就是确保你要移除的空间前面有一个“[”,但如果它前面有一个“]”则没有。
只要你没有嵌套的方括号,那就应该有用,例如:
a a [b [c c] b]
因为在这种情况下,第一个“b”之后的空格将被删除,它将变为:
aa [b [c c] b]
答案 1 :(得分:8)
这听起来不像你真正想要的正则表达式。通过阅读直接解析非常容易。伪代码:
inside_brackets = false;
for ( i = 0; i < length(str); i++) {
if (str[i] == '[' )
inside_brackets = true;
else if str[i] == ']'
inside_brackets = false;
if ( ! inside_brackets && is_space(str[i]) )
delete(str[i]);
}
任何涉及正则表达式的东西都会涉及很多外观,这些东西会反复重复,而且速度会慢得多,而且难以理解。
要使这个适用于嵌套括号,只需将inside_brackets
更改为计数器,从零开始,在开括号上递增,在小括号上递减。
答案 2 :(得分:2)
这对我有用:
(\[.+?\])|\s
然后,当您调用replace函数时,只需传入$ 1的替换值。我们的想法是首先在括号内查找图案,并确保它们不受影响。然后括号外的每个空格都被替换为空。
请注意,我使用Regex Hero(.NET正则表达式测试程序)进行了测试,而不是使用PHP进行测试。所以我不能100%确定这对你有用。
这是一个有趣的。一开始听起来很简单,然后看起来相当困难。然后我终于到达的解决方案确实很简单。我很惊讶解决方案不需要任何形式的外观。它应该比使用环视的任何方法都快。
答案 3 :(得分:1)
如何做到这一点取决于应该做什么:
a b [ c [ d [ e ] f ] g
这是模棱两可的;可能的答案至少是:
ab[ c [ d [ e ] f ]g
ab[ c [ d [ e ]f]g
对于前两种情况,您可以使用regexp。对于第三种情况,使用(小)解析器会更好。
对于一个或两个案例,在第一个[
上拆分字符串。在[
之前删除所有内容(显然在括号之外)。接下来,查找.*\]
(案例1)或.*?\]
(案例2)并将其移至输出。重复,直到你没有输入。
答案 4 :(得分:1)
重新提出这个问题,因为它有一个简单的解决方案,没有提到。
\[[^]]*\](*SKIP)(*F)|\s+
交替的左侧匹配完整的括号组,然后故意失败。右侧匹配并捕获第1组的空格,我们知道它们是正确的空格,因为如果它们在括号内,则左边的表达式会失败。
查看此demo
中的匹配项这意味着你可以做到
$replace = preg_replace("~\[[^]]*\](*SKIP)(*F)|\s+~","",$string);
参考
答案 5 :(得分:0)
以下内容将匹配行首或行括结束(必须在您想要匹配的任何空格之前),后跟任何不是括号或空格的内容,后跟一些空格
/((^|\])[^ \[]*) +/
用$1
替换“all”将从每个非括号序列中删除第一个空格块。您必须重复匹配才能删除所有空格。
示例:
abcd efg [hij klm]nop qrst u
abcdefg [hij klm]nopqrst u
abcdefg[hij klm]nopqrstu
done