2009-07-30 362 views
3

我一直在摔跤我正在希望用正则表达式解决的问题。正则表达式除去括号之间的所有空格

比方说,我有一个字符串,可以包含任何字母数字,并且可能包含方括号内的子字符串。这些子字符串可以像这样出现在字符串中的任何位置。也可以有任意数量的括号子字符串。

实例:

  • AAA [BB B]
  • AAA [BBB] CCC [d DD]
  • [AAA] BBB并[c CC]

可以看到在一些括号内的子字符串中有空格,没关系。我的主要问题,现在的问题是,当我遇到空间这样的支架之外:

  • 一节AA [BB B]

现在我要保留括号内的空间,但在其他地方删除。

这就会变得稍微有点棘手像字符串:

  • 一节AA [BB B](闭杯)[d DD]éEE [F FF]

在这里,我想回报为:

  • AAA [BB b] CCC [d DD] EEE [F FF]

我花了一些现在可以通过关于lookaround,negative assertions等不同章节的不同阅读方式阅读这些内容,并且它让我的头脑旋转起来。

注意:对于访问此的任何人,我没有寻找任何涉及嵌套括号的解决方案。如果是这种情况,我可能会像下面提到的一些评论一样务实地做。

回答

10

此正则表达式应该做的伎俩:

[ ](?=[^\]]*?(?:\[|$)) 

只需更换这与“”相匹配的空间。

基本上它所做的一切都是确保你要删除的空间在它前面有一个“[”,但如果它之前有一个“]”,则不会。

只要你没有嵌套的方括号,例如,这应该工作:

AA [B [CC] B]

因为在这种情况下,之后的第一个 “B” 的空间将被删除,它将成为:

AA [b [CC] b]

+1

+1回答实际的问题:如何执行*这个任务*(即没有嵌套)*用正则表达式*。 – 2009-07-31 02:42:10

+0

太棒了,谢谢。我有点接近,但我无法处理过去两套括号内的子串。我不需要嵌套括号(phew!)。 – seano 2009-07-31 13:48:00

+1

的“| $”末需要的情况下,你的字符串是像“一节AA [BB B](闭杯)[d DD]éEE [F FF; G GG”,摆脱之间的空间的克氏。他们没有跟随他们,所以你也想检查字符串的结尾('$')。你是对的,第一个字符类中的'[''不是必需的。这是因为'。*?b'基本上与'[^ b] * b'相同,只要这是正则表达式的结尾。在我使用'?'之前,这只是我在写作时留下的。字符。但有趣的是,'。+?b'与'[^ b] + b'不同。 – Senseful 2009-07-31 15:29:38

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更改为计数器,从零开始,在打开的括号上递增并在近括号内递减。

1

如何做到这一点取决于什么应该做:

a b [ c [ d [ e ] f ] g 

这是不明确的;可能的答案是至少:

  • ab[ c [ d [ e ] f ]g
  • ab[ c [ d [ e ]f]g
  • 误差出来;括号不匹配!

对于前两种情况下,你可以使用正则表达式。对于第三种情况,使用(小)解析器会更好。

对于任一种情况下一个或两个,划分在第一[的字符串。从[之前一切地带空间(这显然括号外)。接下来,寻找.*\](情况1)或.*?\](案例2)并移动到你的输出。重复,直到你没有输入。

2

这个工作对我来说:

(\[.+?\])|\s 

然后你只需传递$ 1的重置价值,当你调用替换功能。这个想法是首先查找括号内的模式,并确保它们未被触摸。然后括号外的所有空间都被替换为空。

请注意,我用正则表达式英雄(一个.NET正则表达式测试仪),而不是在PHP中测试这一点。所以我不是100%肯定这会适合你。

这是一个有趣的一个。听起来很简单,然后看起来相当困难。然后我终于到达的解决方案确实很简单。我很惊讶这个解决方案不需要查看任何形式的内容。它应该比使用lookaround的任何方法都快。

0

以下内容将匹配行首或括号末尾(必须出现在您想要匹配的任何空格之前),后面跟着任何不是开始括号或空格的字符,后跟一些空间。

/((^|\])[^ \[]*) +/ 

$1取代“所有”将从每个非括号序列去除的空间的第一个块。您将不得不重复该比赛以删除所有空格。

例子:

abcd efg [hij klm]nop qrst u 
abcdefg [hij klm]nopqrst u 
abcdefg[hij klm]nopqrstu 
done 
0

复活这个问题,因为它有这样的没有提到一个简单的解决方案。

\[[^]]*\](*SKIP)(*F)|\s+ 

交替的左侧匹配完整的括号组然后故意失败。右侧匹配和捕捉空间,以第1组,我们知道他们是正确的空格,因为如果他们是括号内他们会一直未能在左边的表达。

看到比赛在这个demo

这意味着你可以做

$replace = preg_replace("~\[[^]]*\](*SKIP)(*F)|\s+~","",$string); 

参考

  1. How to match pattern except in situations s1, s2, s3
  2. How to match a pattern unless...
相关问题