Замените часть строки между кавычками в регулярном выражении php

Теперь у меня есть очень базовые навыки работы с регулярными выражениями, я использовал регулярное выражение только пару раз для базовых вещей. Вероятно, этот вопрос уже задавался ранее, за что я извиняюсь, но я не смог найти ответа на этот вопрос. Нашел похожий, правда и пытался его приспособить но безрезультатно. Хорошо, на вопрос - Как заменить пробел только между определенными символами (в данном случае двойными кавычками)?

Скажем, у меня есть следующая строка:

Модкаст "подкаст миссии" A B C "D E F"

Я хочу заменить пробелы между миссией и подкастом, а также пробелами между D, E и F, оставив остальные нетронутыми.

P.S. Что, если пробел был строкой? Пример для этого также приветствуется.

Немного отредактировал, надеюсь теперь стало понятнее. Редактировать 2: мне нужно сделать это в строке в php и выполнить ее в оболочке. Редактировать 3: извините, я изменил весь вопрос 3 раза, просто я сам совсем запутался. Ваше здоровье!


person GGets    schedule 02.07.2013    source источник
comment
Итак, что вы пробовали до сих пор?   -  person Mike Brant    schedule 02.07.2013
comment
можете ли вы привести больше примеров, кроме find /vol_stor/8s8a912hj1 | grep ""mission\|podcast"" | grep "modcast" ? по крайней мере 2 варианта очень помогут   -  person Angga    schedule 02.07.2013
comment
ну, я ничего не пробовал, так как не знаю, как сохранить часть совпадающей строки внутри и заменить только то, что находится внутри слов, которые находятся между скобками. Так что, я открыт для всех видов предложений :)   -  person GGets    schedule 02.07.2013
comment
замените это регулярное выражение (")("\w+)(.*?)(\w+")(") на $2 $4   -  person Angga    schedule 02.07.2013
comment
одна скобка = 1 группа, и вы можете представить эту 1 группу как один $ при ее замене. вам просто нужно добавить, какую группу вы хотите добавить. и вы также можете добавить дополнительные строки в эту замену.   -  person Angga    schedule 02.07.2013
comment
Почему PHP является одним из тегов?   -  person chrislondon    schedule 02.07.2013
comment
Я пробовал предложение Анги, но не мог понять. мне нужно поместить их в кавычки с пробелом внутри них? Спасибо!   -  person GGets    schedule 02.07.2013
comment
Вы пытаетесь просто избавиться от любых неалфавитных символов с помощью одного пробела?   -  person Michael Wheeler    schedule 02.07.2013
comment
перейдите по этой ссылке, эта ссылка покажет вам, как я анализирую (ваш первый пример перед редактированием) find /vol_stor/8s8a912hj1 | grep ""mission\|podcast"" | grep "modcast" до "mission podcast"   -  person Angga    schedule 02.07.2013
comment
и после того, как вы отредактировали свой вопрос, ваш жирный текст стал очень случайным. пожалуйста, исправьте эту исходную строку и ожидаемое значение из этой строки   -  person Angga    schedule 02.07.2013
comment
боже мой, я просто не могу выделить жирным шрифтом то, что хочу :( Я хочу сохранить слова, но изменить пробел в середине, но оставить все остальные пробелы   -  person GGets    schedule 03.07.2013


Ответы (3)


Описание

Я бы решил эту проблему, сначала разбив строку на группы строк в кавычках или без них.

Затем выполняется итерация совпадений, и если группа захвата 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"
person Ro Yo Mi    schedule 02.07.2013
comment
Большое спасибо за ответ и за то, что нашли время, чтобы проиллюстрировать его! И поскольку это было бы идеально, я надеялся, что смогу избежать разбиения на массивы. Есть ли у вас какие-либо предложения по поводу preg_replace? - person GGets; 03.07.2013
comment
на самом деле это было выражение foreach, которого я пытался избежать, но в любом случае это прекрасно. Большое спасибо! - person GGets; 03.07.2013
comment
Что, если пробел был строкой? Могу ли я сопоставить целую строку? - person GGets; 03.07.2013
comment
неважно я разобрался. если какой-нибудь нуб вроде меня задается вопросом, \s в echo preg_replace('/\s(?=.*?")/ims','~~new~~',$entry); следует заменить строкой, которую вы хотите заменить. Всем большое спасибо! - person GGets; 03.07.2013
comment
Не могли бы вы объяснить часть (?=.*?") в последнем регулярном выражении? - person Tomas M; 31.10.2015
comment
Неважно, я обнаружил, что (?= называется lookakead, и смог узнать, как его использовать, здесь regular-expressions .info/lookaround.html - person Tomas M; 01.11.2015
comment
@TomasM да, этот сайт крут. Он четко описывает, как работают регулярные выражения. - person Ro Yo Mi; 06.11.2015

Если вам не нужно использовать регулярные выражения, вот итеративная версия, которая работает:

<?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";
?>
person Sean Bright    schedule 02.07.2013
comment
да, но не требует ли повторение больше ресурсов, не занимает ли это больше времени? - person GGets; 03.07.2013
comment
Только что провел прямой тест, и (вопреки моей интуиции) реализация регулярного выражения действительно быстрее. Я списываю это на разницу между нативным кодом (расширение PCRE реализовано на C) и интерпретируемым PHP-кодом. - person Sean Bright; 03.07.2013

Весь foreach вообще не нужен! Для этого можно использовать однострочный.

Вот код, который заменяет пробелы в строках в кавычках. Идея состоит в том, что если пробел находится внутри кавычек, за ним следует нечетное количество кавычек. Это можно сделать с помощью регулярного выражения.

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

Это все! Как это устроено? Он соответствует всем символам \s, за которыми не следует четное количество кавычек. Соответствующие пробелы заменяются на x. Конечно, вы можете изменить его на любое желаемое значение или оставить пустым.

person Tomas M    schedule 31.10.2015
comment
это перестает работать, если у вас где-то нет закрывающей кавычки, поэтому представьте строку, содержащую несколько текстовых сегментов в кавычках, и вы оставляете закрывающую кавычку выключенной, это становится дурацким - person jackrabbithanna; 26.06.2017