Замена соответствующих строк из ключей массива в строку - PullRequest
0 голосов
/ 22 января 2020

Моя цель состоит в том, чтобы в строке найти ключи предполагаемого массива и в этой строке заменить эти ключи соответствующими ключами из массива.

У меня есть небольшая полезная функция, которая находит все мои строки между 2 разделителями (ссылка в песочнице: https://repl.it/repls/UnlinedDodgerblueAbstractions):

function findBetween( $string, $start, $end )
{
    $start = preg_quote( $start, '/' );
    $end = preg_quote( $end, '/' );

    $format = '/(%s)(.*?)(%s)/';

    $pattern = sprintf( $format, $start, $end );

    preg_match_all( $pattern, $string, $matches );

    $number_of_matches = is_string( $matches[2] ) ? 1 : count( $matches[2] );

    if( $number_of_matches === 1 ) {
        return $matches[2];
    }

    if( $number_of_matches < 2 || empty( $matches ) ) {
        return False;
    }

    return $matches[2];
}

Пример:

findBetween( 'This thing should output _$this_key$_ and also _$this_one$_ so that I can match it with an array!', '_$', '$_')

Должен вернуть массив со значениями ['this_key', 'this_one'] как оно есть. Вопрос в том, как я могу взять их и заменить их значениями ассоциативного массива?

Предположим, мой массив такой:

[
    'this_key' => 'love',
    'this_one' => 'more love'
];

Мой вывод должен быть таким:

This thing should output love and also more love so that I can match it with an array!

Как мне этого добиться?

Ответы [ 3 ]

1 голос
/ 22 января 2020

Эта проблема может быть более легко решена с помощью strtr, чем регулярное выражение. Мы можем использовать array_map, чтобы добавить значения $start и $end вокруг клавиш $replacements, а затем использовать strtr для подстановки:

$str = 'This thing should output _$this_key$_ and also _$this_one$_ so that I can match it with an array!';
$replacements = [
    'this_key' => 'love',
    'this_one' => 'more love'
];
$start = '_$';
$end = '$_';
$replacements = array_combine(array_map(function ($v) use ($start, $end) { return "$start$v$end"; }, array_keys($replacements)), $replacements);
echo strtr($str, $replacements);

Вывод:

This thing should output love and also more love so that I can match it with an array!

Демонстрация на 3v4l.org

Если производительность является проблемой, потому что вам приходится каждый раз регенерировать массив $replacements, это l oop намного быстрее:

foreach ($replacements as $key => $value) {
    $new_reps["_\$$key\$_"] = $value;
}

Сравнение производительности демо на 3v4l.org

1 голос
/ 22 января 2020

Вы можете использовать preg_replace_callback :

<?php

$str = 'This thing should output _$this_key$_ and also _$this_one$_ so that I can match it with an array!';

$replacements = [
    'this_key' => 'love',
    'this_one' => 'more love'
];

$replaced = preg_replace_callback('/_\$([^$]+)\$_/', function($matches) use ($replacements) {
    return $replacements[$matches[1]];
}, $str);

print $replaced;

У вас есть демо здесь .

Регулярное выражение, объясненное:

_              # Literal '_'
\$             # Literal '$' ($ needs to be scaped as it means end of line/string)
(              # Begin of first capturing group
    [^$]+      # One carcter that cannot be "$", repeated 1 or more times
)              # End of first capturing group
\$             # Literal '$'
_              # Literal '_'

Для каждого совпадения соответствующие данные ($mathces) передаются в функцию.

В первом элементе массива есть первая группа захвата, что мы используем для замены.

0 голосов
/ 22 января 2020

Надеюсь, это решит ваш ответ на вопрос!

$items['this_key'] = 'love';
$items['this_one'] = 'more love';

$string = 'This thing should output _$this_key$_ and also _$this_one$_ so that I can match it with an array!';

$this_key = $items['this_key'];
$this_one = $items['this_one'];
$string = str_replace('_$this_key$_',$this_key,$string);
$string = str_replace('_$this_one$_',$this_one,$string);

echo  $string;
...