当前位置: 首页 > 知识库问答 >
问题:

没有正则表达式:引号之间的字符串?

拓拔俊德
2023-03-14

我正在创建一个单词替换脚本。我遇到了一个路障,忽略引号之间的字符串,并且在这里找不到一个不涉及正则表达式的体面解决方案。

我有一个工作片段,它循环遍历字符串中的每个字符,并计算出最近的报价是开始报价还是结束报价(无论是单引号还是双引号),并忽略转义报价。问题是,为了提供100%准确的体验,它必须在每次字符串更改时运行(由于它的工作方式,它可以在单个函数中更改60K次),并且由于字符串长度的可能性,代码即使在相当短的脚本上也需要太长的时间。

有没有一种快速的方法来确定字符串是否在开放和关闭引号之间(单引号和双引号)?忽略逃脱了"和"。或者,您是否有关于如何优化代码段以使其运行更快的建议?删除此功能后,进程几乎以首选速度(即时)运行。

作为练习,考虑使用包含文本的变量将代码片段复制并粘贴到脚本中。例如$thisIsAQuote="这是一个报价。";从那时起,所有内容都应该正确替换,除了$thisIsAQuote应该保留其确切文本。

但问题是:我发现的其他解决方案将处理“这是一句引语”和...$this-

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

    $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似乎只是替换了整个字符串的“一些”部分,这就是迭代次数到位的原因。它循环通过的时候循环,直到任何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;

“键”和“答案”是包含不同长度单词的数组formatted'是包含更改信息的新字符串“initializeQuoted”是上面的代码段。我使用HTMLEntity和html_entity_decode来帮助消除带有键/应答替换的空白。

忽略神奇的数字(5和10K)。

共有2个答案

越扬
2023-03-14

我只是在做这个。希望这能给你一些额外的想法。

MATCH: ["]([\w\s\(\)\.\d\_\-\[\]\{\}]+|\s*)["]

REPLACE: ""

<?xml version="1.0" encoding="UTF-8"?>
<NotepadPlus>
    <ScintillaContextMenu>
        <!--
        NOTES: BLAH
        -->
        [WEBSITE]
        https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/PowerEditor/installer/nativeLang/english.xml
            -->
        <Item MenuId="Tools" MenuItemName="Generate..."/>
        <Item MenuEntryName="Edit" FolderName="Remove Lines" MenuItemName="Remove Empty Lines" ItemNameAs="Empty Lines"/>
        <Item MenuEntryName="Plugins" FolderName="Remove Lines" MenuItemName="Remove duplicate lines" ItemNameAs="Duplicate Lines (Plugin)"/>
        <Item MenuEntryName="Edit" FolderName="Remove Lines" MenuItemName="Remove Consecutive Duplicate Lines" ItemNameAs="Duplicate Lines"/>
        <Item MenuEntryName="Search" FolderName="Add Style Tokens" MenuItemName="Using 1st Style" ItemNameAs="1"/>
        <Item id="45003" Foldername="Convert" ItemNameAs="Macintosh (CR)"/>
        <Item id="0" FolderName="XML Tools"/>
        <Item MenuEntryName="Plugins" FolderName="XML Tools" MenuItemName="Options..." ItemNameAs="Options"/>

    </ScintillaContextMenu>
</NotepadPlus>

如果你想出别的办法,请告诉我。

严子默
2023-03-14

如果我理解正确,您可以这样做:

$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次,并每次进行所需的最小检查次数,因此很难减少更多。如果您需要更快的方法,例如在客户端逐步进行一些拆分,而不是在服务器端对整个字符串进行拆分,也许您应该从头开始修改您的方法。

 类似资料:
  • 这是我之前问题的后续。我意识到我需要更具体地说明我的regex案例,以获得适用于我的案例的答案。 我已经与这个正则表达式斗争了很长一段时间(也使用我上一个问题的答案),我似乎无法构建我需要的东西。 我需要将所有字符串中出现的两个重复出现的单引号替换为(因此字符串内部意味着单引号)。这是因为在一种语言(语法)中,字符串中的引号使用<code>‘转义。 这里有一个例子(实际的例子可以包含用< code

  • 问题内容: 我试图用Java写一个正则表达式来查找单引号之间的内容。可以帮我吗?我尝试了以下操作,但在某些情况下不起作用: 测试案例: “ Tumblr”是一个了不起的应用程序 预期输出: Tumblr 测试用例: Tumblr是一个了不起的“应用程序” 预期输出: 应用程序 测试用例: Tumblr是一个“惊人的”应用程序 预期输出: 惊人的 测试用例: Tumblr很棒而且令人惊讶 预期输出:

  • 如何替换文本文件中两个引号之间的所有输入。第一个引号总是前面有一个选项卡,或者它是行中的第一个字符(csv文件)。我尝试了以下正则表达式 但是这个正则表达式只匹配两个引号之间的第一个输入,而不是全部。 例如,以下文本: 应成为 我读了下面的文章(javascript正则表达式替换括号之间的空格),非常相似,但正则表达式建议在我的情况下不可用。

  • 我需要替换以下字符串中的引号。 最终输出应该是“这是test()ing和test()ing”; i、 e仅当它以“test()开头,以”结尾时才替换。中间的文本保持不变。 这个坏了。 请为同样的问题推荐合适的正则表达式。

  • 我面临一个挑战,要以以下格式匹配输入: 输入由key=value对组成。关键字以斜杠开头。值可以是数字或引号中的字符串。 该值可以选择性地包含转义引号,即引号后面跟着引号(“”)。这种转义引号应该被视为价值的一部分。不需要检查转义引号是否平衡(例如,由另一个转义引号结束)。 正则表达式应该匹配序列中给定的key=value部分,并且对于长输入(例如value是10000个字符)不应该中断。