【问题标题】:Replace part of string between quotes in php regex替换php正则表达式中引号之间的部分字符串
【发布时间】:2013-06-30 04:31:30
【问题描述】:

现在我已经掌握了非常基本的正则表达式技能,只在基本的东西上使用了几次正则表达式。以前可能有人问过这个问题,对此我深表歉意,但我找不到任何答案。发现类似的,虽然并试图适应它,但无济于事。 好的,关于问题 - 如何仅在某些字符之间替换空格(在这种情况下为双引号)?

假设我有以下字符串:

“任务播客”modcast A B C “D E F”

我想替换 missionpodcast 之间的空格以及 DE 之间的空格& F,而其他的保持不变。

附:如果空格是字符串呢?也欢迎举个例子。

对此进行了一些编辑,希望现在更清楚。 编辑 2:我需要对 php 中的字符串执行此操作并在 shell 中执行它。 编辑3:对不起,我把整个问题改了3次,只是我自己很困惑。干杯!

【问题讨论】:

  • 那么到目前为止你尝试过什么?
  • 你能提供除find /vol_stor/8s8a912hj1 | grep ""mission\|podcast"" | grep "modcast"之外的更多例子吗?至少 2 个变体会有很大帮助
  • 好吧,我没有尝试过任何事情,因为我不知道如何在其中保留部分匹配的字符串,并且只替换括号之间的单词中的内容。所以,我愿意接受各种建议:)
  • $2 $4替换这个正则表达式(")("\w+)(.*?)(\w+")(")
  • 为什么 PHP 是标签之一?

标签: php regex substring quotes double-quotes


【解决方案1】:

说明

我会通过首先将字符串分成带引号或不带引号的字符串组来解决这个问题。

然后遍历匹配项,如果填充了捕获组 1,则引用该字符串,因此只需对替换捕获组 0 进行简单替换。如果未填充捕获组 1,则跳到下一个匹配项。

在每次迭代中,您都希望简单地构建一个新字符串。

由于拆分字符串是困难的部分,我会使用这个正则表达式:

("[^"]*")|[^"]*

示例

示例文本

"mission podcast" modcast A B C "D E F"

代码

PHP Code Example: 
<?php
$sourcestring="your source string";
preg_match_all('/("[^"]*")|[^"]*/i',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>

捕获组

$matches Array:
(
    [0] => Array
        (
            [0] => "mission podcast"
            [1] =>  modcast A B C 
            [2] => "D E F"
            [3] => 
        )

    [1] => Array
        (
            [0] => "mission podcast"
            [1] => 
            [2] => "D E F"
            [3] => 
        )

)

PHP 示例

这个 php 脚本将只替换带引号的字符串中的空格。

工作示例:http://ideone.com/jBytL3

代码

<?php

$text ='"mission podcast" modcast A B C "D E F"';

preg_match_all('/("[^"]*")|[^"]*/',$text,$matches);

foreach($matches[0] as $entry){
    echo preg_replace('/\s(?=.*?")/ims','~~new~~',$entry);
    }

输出

"mission~~new~~podcast" modcast A B C "D~~new~~E~~new~~F"

【讨论】:

  • 非常感谢您的回答和花时间来说明它!因为它会做得很完美,我希望我可以避免分成数组。您对 preg_replace 有什么建议吗?
  • 实际上这是我试图避免的 foreach 语句,但是,无论如何,这很完美。非常感谢!
  • 如果空格是字符串怎么办?我可以匹配整个字符串吗?
  • 没关系,我想通了。如果像我这样的菜鸟想知道,echo preg_replace('/\s(?=.*?")/ims','~~new~~',$entry); 中的 \s 应该替换为您要替换的字符串。非常感谢大家!
  • 您能解释一下最后一个正则表达式中的(?=.*?") 部分吗?
【解决方案2】:

如果您不需要使用正则表达式,这里有一个可以使用的迭代版本:

<?php
    function remove_quoted_whitespace($str) {
        $result = '';
        $length = strlen($str);
        $index = 0;
        $in_quotes = false;

        while ($index < $length) {
            $c = $str[$index++];

            if ($c == '"') {
                $in_quotes = !$in_quotes;
            } else if ($c == ' ') {
                if ($in_quotes) {
                    continue;
                }
            }

            $result .= $c;
        }

        return $result;
    }

    $input = '"mission podcast" modcast A B C "D E F"';
    $output = remove_quoted_whitespace($input);

    echo $input . "\n";
    echo $output . "\n";
?>

【讨论】:

  • 是的,但是迭代不是更耗费资源,不是需要更长的时间吗?
  • 刚刚进行了面对面的测试,并且(与我的直觉相反)正则表达式的实现确实更快。我将其归结为本机代码(PCRE 扩展是用 C 实现)与解释的 PHP 代码之间的差异。
【解决方案3】:

根本不需要整个foreach!可以为此使用单线。

这是替换引号字符串中的空格的代码。这个想法是,如果空格在引号内,则后面跟着奇数个引号。可以通过正则表达式前瞻来完成。

echo preg_replace('{\s+(?!([^"]*"[^"]*")*[^"]*$)}',"x",$str);

就是这样!这个怎么运作?它匹配所有 \s 字符,这些字符后面没有偶数个引号。匹配的空格被 x 替换。您当然可以将其更改为任何所需的值或将其留空。

【讨论】:

  • 如果你在某处没有右引号,这将停止工作,所以想象一个有多个带引号的文本段的字符串,而你没有关闭右引号,它就会变得古怪
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
  • 2017-11-27
相关资源
最近更新 更多