php регулярное выражение для извлечения одного значения параметра из строки - PullRequest
1 голос
/ 08 апреля 2020

Я работаю со строкой, содержащей параметры, разделенные некоторыми специальными символами в PHP с preg_match

Примером может быть такой, который имеет четыре параметра.

1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?

За каждым именем параметра следует? #?, И его значение находится рядом с ним, заканчиваясь? @? (примечание: значения могут быть строками или числами и даже специальными символами)

Я, вероятно, слишком усложнил свое регулярное выражение, которое работает в НЕКОТОРЫХ случаях, но не в том случае, если я ищу последний параметр в строке ..

В этом примере возвращается 2222 как правильное значение (в группе 1) для 2ndParm

(?:.*)2ndParm\?#\?(.*?)\?@\?(?=.)(.*)

, но происходит сбой, если 2ndParm является последним в строке, как в следующем примере:

1stparm?#?1111?@?2ndParm?#?2222?@?

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

Ответы [ 3 ]

2 голосов
/ 08 апреля 2020

Без регулярного выражения:

$str ='1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?';

$keyval = explode('?@?', trim($str, '?@'));

$result = [];

foreach($keyval as $item) {
    [$key, $result[$key]] = explode('?#?', $item);
}

print_r($result);

демо

2 голосов
/ 08 апреля 2020

Вам не нужно использовать регулярные выражения для всего, и вы должны серьезно поговорить с тем, кто придумал этот ужасный формат, о том, что существуют JSON, YAML, TOML, XML, et c.

function bizarre_unserialize($in) {
    $tmp = explode('?@?', $in);
    $tmp = array_filter($tmp); // remove empty
    $tmp = array_map(
        function($a) { return explode('?#?', $a); },
        $tmp
    );
    // rearrange to key-value
    return array_combine(array_column($tmp, 0), array_column($tmp, 1));
}

$input = '1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?';

var_dump(
    bizarre_unserialize($input)
);

Выход:

array(4) {
  ["1stparm"]=>
  string(4) "1111"
  ["2ndParm"]=>
  string(4) "2222"
  ["3rdParm"]=>
  string(4) "3333"
  ["4thparm"]=>
  string(3) "444"
}
1 голос
/ 08 апреля 2020

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

(?P<key>.+?)
\Q?#?\E
(?P<value>.+?)
\Q?@?\E

в режиме verbose, см. демонстрацию на regex101.com .


Конструкция \Q...\E отключает ? и # "суперсилы" (здесь нет необходимости избегать их).
В PHP это может быть
<?php
$string = "1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?";

$regex = "~(?P<key>.+?)\Q?#?\E(?P<value>.+?)\Q?@?\E~";

preg_match_all($regex, $string, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
    echo $match["key"] . " = " . $match["value"] . "\n";
}

?>

Что дает

1stparm = 1111
2ndParm = 2222
3rdParm = 3333
4thparm = 444


или короче:
$result = array_map(
    function($x) {return array($x["key"] => $x["value"]);}, $matches);
print_r($result);
...