没有正则表达式:行情之间的字符串?

问题描述:

我正在创建一个单词替换脚本。我遇到了一个忽略引号之间的字符串的路障,一直没能找到一个不涉及正则表达式的体面解决方案。没有正则表达式:行情之间的字符串?

我有一个工作的片断,通过串并计算出是否与最近的报价在每一个字符的周期是一个打开或关闭引号(无论是单人或双人),并忽略转义的引号。问题是,为了提供100%准确的体验,每次字符串更改时都必须运行(由于它的工作原理,在单个函数中它可能会改变超过60K次),并且由于字符串长度潜在的代码需要很长的时间,即使是一个相当短的脚本。

有没有想出一个字符串是否是打开和关闭引号(单双)之间的快捷方式?忽略溢出“和”。或者,你有关于如何优化代码片段以使其运行速度显着加快的建议?删除此功能后,该进程几乎以首选速度运行(即时)

作为练习,考虑例如$ thisIsAQuote =“这是一个引号”;并且从这一点开始,除了$ thisIsAQuote应该保留其确切的文字外,所有的东西都应该正确地替换。

但这里的问题:其他的解决方案,我发现将把之间的一切“这是一个报价。”和... $这个 - >格式化[$ I - 1] =“......仿佛它仍然引号之间! 。因为就这些解决方案而言,“这是一个报价”中的最后一句话。并且if-check中的第一个引号是打开和关闭的引号。另一个明显的问题是一些字符串包含带撇号的单词。撇号不应被视为单引号,但在我找到的所有解决方案中,它们都是。

换句话说,他们是“不知道”的解决方案。

$quoteClosed = true; 
    $singleQuoteClosed = true; 

    $codeLength = mb_strlen($this->formatted); 
    if ($codeLength == false) 
     return; 

    for ($i = 0; $i < $codeLength; $i++) 
    { 
     if ((!$quoteClosed || !$singleQuoteClosed) && ($this->formatted[$i] == '"' || $this->formatted[$i] == "'")) 
     { 
      if (!$quoteClosed && $this->formatted[$i - 1] != "\\") 
       $quoteClosed = true; 
      else if (!$singleQuoteClosed && $this->formatted[$i - 1] != "\\") 
       $singleQuoteClosed = true; 
     } 
     else if ($this->formatted[$i] == '"' && ($i <= 0 || $this->formatted[$i - 1] != "\\")) 
     { 
      if ($quoteClosed && $singleQuoteClosed) 
       $quoteClosed = false; 
     } 
     else if ($this->formatted[$i] == "'" && ($i <= 0 || $this->formatted[$i - 1] != "\\")) 
     { 
      if ($singleQuoteClosed && $quoteClosed) 
       $singleQuoteClosed = false; 
     } 

     if ($quoteClosed && $singleQuoteClosed) 
      $this->quoted[$i] = 0; 
     else 
      $this->quoted[$i] = 1; 
    } 

如果没有一种方法,使上述更高效,是有一个非正则表达式的方式来快速替换与子阵列中的所有子在第二阵列,而不在整个字符串中缺少任何?

substr_replace和str_replace函数似乎只是更换整个字符串,这就是为什么迭代次数到位的“一些”作品。它循环一个while循环,直到任何strpos认为字符串不存在为止(它似乎从来没有做过......我可能错误地使用它),或者循环10K次,以先发生者为准。

运行上面的代码片段 - 每一轮将解决速度问题,但这留下了“完全替换”的问题,当然,保持意识到它应该避免替换引号内的任何内容。

for ($a = 0; $a < count($this->keys); $a++) 
    { 
     $escape = 0; 
     if ($a > count($this->keys) - 5) 
      $this->formatted = $this->decodeHTML($this->formatted); 

     while (strpos($this->formatted, $this->keys[$a]) !== false) 
     { 
      $valid = strpos($this->formatted, $this->keys[$a]); 
      if ($valid === false || $this->quoted[$valid] === 1) 
       break; 

      $this->formatted = substr_replace($this->formatted, $this->answers[$a], $valid, mb_strlen($this->keys[$a])); 
      $this->initializeQuoted(); 
      $escape++; 

      if ($escape >= 10000) 
       break; 
     } 

     if ($a > count($this->keys) - 5) 
      $this->formatted = html_entity_decode($this->formatted); 
    } 
    $this->quoted = array(); 
    $this->initializeQuoted(); 
    return $this->formatted; 

'keys'和'answers'是包含各种长度的单词的数组。 '格式化'是具有改变的信息的新字符串。 'initializeQuoted'是上面的代码片段。我使用htmlentities和html_entity_decode来帮助摆脱键/回答替换空白。

忽略幻数(5S和10K)。

+1

你有没有想过只是先打电话给该功能?也许这会很好。 –

+0

你是指在while循环之前运行函数吗?我已经这样做了,但是它会导致严重的错误(很多错过的更改),因为while循环执行更改,并且在进行单一更改时quote-tracker不再是最新的,更不用说几个了。自然,每次在while循环后运行函数都有完全相同的问题。 –

+0

_“撇号不应被视为单引号,但在我找到的所有解决方案中,它们都是。” - 这可能是由于该要求的复杂性,尽管您只是简单地将它扔在冷漠的“哦,我也需要这个,但这应该不是什么大事”。 “如果我没有记错的话,那本书的标题是'汉斯最喜欢的诗'。” - 现在你告诉我你期望弄清楚哪一个是正确的结尾单引号的脚本逻辑?这需要了解_human language_,所以你在这里接近AI功能。 – CBroe

如果我理解正确的话,那么你可以这样做:

$replacements = [ 
    "test" => "banana", 
    "Test" => "Banana" 
]; 

$brackets = [[0]]; 
$lastOpenedQuote = null; 



for ($i = 0;$i < strlen($string);$i++) { 

    if ($string[$i] == "\\") { $i++; continue; } //Skip escaped chars 

    if ($string[$i] == $lastOpenedQuote) { 
     $lastOpenedQuote = null; 
     $brackets[count($brackets)-1][] = $i; 
     $brackets[] = [ $i+1 ]; 
    } elseif ($lastOpenedQuote == null && ($string[$i] == "\"" || $string[$i] == "'")) { 
     $lastOpenedQuote = $string[$i]; 
     $brackets[count($brackets)-1][] = $i-1; 
     $brackets[] = [ $i ]; 
    } 
} 
$brackets[count($brackets)-1][] = strlen($string)-1; 

$prev = 0; 
$bits = []; 
foreach ($brackets as $index => $pair) { 
    $bits[$index] = substr($string,$pair[0],$pair[1]-$pair[0]+1); 
    if ($bits[$index][0] != "\"" && $bits[$index][0] != "'") { 
     $bits[$index] = str_replace(array_keys($replacements),array_values($replacements), $bits[$index]); 
    } 
} 

瞧瞧吧:http://sandbox.onlinephpfunctions.com/code/0453cb7941f1dcad636043fceff30dc0965541ee

现在,如果性能仍然是一个问题,记住这个经历每一串字符1次并且每次都需要进行最少次数的检查,所以很难将其减少更多。也许你应该修改你的方法,从底部开始,如果你需要更快的东西,比如说。在客户端逐渐进行一些拆分,而不是在服务器端的整个字符串上进行拆分。

+0

呵呵。我将不得不剖析它,但看着沙箱,看起来像是会起作用。谢谢! –