2012-02-09 150 views
2

我试图找到合适的正则表达式做以下情况除外:正则表达式替换所有点字符串,当一轮大括号

输入:“$ MM.Player.Panning(1 0.1)”; output'$ MM-> Player-> Panning(1,0.1)';

我无法弄清楚如何用' - >'替换圆点,而无需在圆括号之间替换圆点。

任何输入或建议,将不胜感激

+0

注:各种数据的圆形支架之间传递,包括JSON-字符串,它可能包含字符串本身。 – 2012-02-09 15:25:03

回答

1

最好的解决方案是而不是使用正则表达式。

尝试一个小功能,它分析你的字符串这样的:

(在PHP函数,我不知道你使用的是什么语言)

function dotReplacer($string) { 
    $parenthesis = 0; // Counts if we are inside parenthesis or not. 
    $listOfDots = array(); // List of the index of the $string which contain dots to replace. 
    $listOfElements = array(); // List of elements between these dots. e.g.: $MM, Player and Panning(1, 0.1) 
    $newString = ''; // The new string to return. 
    for ($i = 0; $i < strlen($string); $i++) { // Check with every character in the $string... 
    switch (substr($string, $i, 1)) { 
     case '(': 
     $parenthesis++; // If we see an opening parenthesis, increase the level. 
     break; 

     case ')': 
     $parenthesis--; // If we see a closing parenthesis, decrease the level. 
     break; 

     case '.': 
     if ($parenthesis == 0) { 
      $listOfDots[] = $i; // If we see a dot AND we are not inside parenthesis, include the character index in the list to replace. 
     } 
     break; 

     default: 
    } 
    } 

    $iterator = 0; // Beginning at the start of the string... 
    foreach ($listOfDots as $dot) { 
    $listOfElements[] = substr($string, $iterator, $dot - $iterator); // Add the element that is between the iterator and the next dot. 
    $iterator = $dot + 1; // Move the iterator after the dot. 
    } 
    $listOfElements[] = substr($string, $iterator); // Do that one more time for everything that takes place after the last dot. 
    return implode('->', $listOfElements); // Return an imploded list of elements with '->' between the elements. 
} 

它完美,我试过了。你的输入和输出是正确的。

+0

嘿Oltarus。为什么我不应该使用正则表达式并使用脚本,而脚本更复杂? – 2012-02-11 17:02:13

+0

因为正则表达式在每种情况下都不起作用。我的脚本。现在,如果您使用非常精确的语法,例如您只需要识别小数点,请使用正则表达式。我的脚本也适用于像'gpd.ar(gfo.ffe).p2v'→'gpd-> ar(gfo.ffe) - > p2v'这样的字符串。这真的取决于你,我只是给出了你所问的完整答案......我很开心创建该脚本,这可能是我在这个过程中的主要目标。 – SteeveDroz 2012-02-12 10:46:30

+0

aha多数民众赞成在明确。但我的解决方案对我来说已经足够了,所以我只会使用它;) – 2012-02-12 18:55:51

1

一个建议是:(因为你很可能会通过在括号内的数字和点外是由非数字环绕)

尝试(\D)\.(\D),代之以$1->$2

+0

@Peter Elzinga只有当你想要保存的'。'数字时才有效。你确定这是你想要的吗?另外:要小心,它不适用于“平移(1,0)”。 – SteeveDroz 2012-02-09 15:05:10

+1

这样做的伎俩......不能用正则表达式生成器得到这个...**需要在可用时间学习正则表达式**问题 – 2012-02-09 15:12:19

+0

@Oltarus其他函数确实需要包含字符串的json-strings,因此用户输入的字符串可能包含点。你有更好的解决方案来防止由于输入无效造成的错误吗? – 2012-02-09 15:29:09

0

彼得,你说:

,如果你有一个更简单的,更小的解决方案,我仍想知道

简单和更小的是好的? :)

这里是整个解决方案:

$regex = '~\([^)]*\)(*SKIP)(*F)|(\.)~'; 
$subject = '$MM.Player.Panning(1, 0.1)'; 
$replaced = preg_replace($regex,"->",$subject); 

你的情况是直出Match (or replace) a pattern except in situations s1, s2, s3 etc。我们用这个简单的正则表达式:

\([^)]*\)(*SKIP)(*F)|\. 

交替的左侧匹配完整(parenthesized expressions)然后故意失败,跳过绳的那部分。右侧匹配点,我们知道它们是正确的点,因为它们与左侧的表达式不匹配。

这些是我们需要替换的点。您可以在online demo的底部看到结果。

参考

How to match (or replace) a pattern except in situations s1, s2, s3...