#php #regex
#php #регулярное выражение
Вопрос:
Я пытаюсь сопоставить пользователей из старого дампа DOS, чтобы их можно было перенести на что-то новое. Они начинаются со %
знака и заканчиваются на ]
. Некоторые в одной строке, а другие во многих строках.
https://regex101.com/r/0h5ndW/1
Мое регулярное %([^%]*)]
выражение работает, но есть ли лучший способ выбрать каждого пользователя, начиная с %
до ]
(включая %
и ]
), чтобы я мог пропустить их preg_replace
и манипулировать ими позже?
Я немного скептически отношусь к многострочной части.
Expected Output
%user:100 [ type=admin, added=10/12/1997, last-login:10/20/1997, total-logins:45, status:1 ]
%user:111 [ type=user, added=10/12/1997, last-login:10/27/1997, total-logins:145, status:1 ]
%user:112 [ type=viewer, added=10/12/1997, last-login:10/23/1997, total-logins:6, status:1 ]
%user:113 [ type=viewer, added=10/12/1997, last-login:10/14/1997, total-logins:2, status:1]
%user:114 [ type=viewer, added=10/12/1997, last-login:10/14/1997, total-logins:1, status:1]
%user:115 [ type=viewer, added=10/12/1997, last-login:10/12/1997, total-logins:1, status:1 ]
Необработанные данные
%user:100 [
type=admin,
added=10/12/1997,
last-login:10/20/1997,
total-logins:45,
status:1
]
%user:111 [
type=user,
added=10/12/1997,
last-login:10/27/1997,
total-logins:145,
status:1
]
%user:112 [ type=viewer, added=10/12/1997,
last-login:10/23/1997,
total-logins:6,
status:1
]
%user:113 [ type=viewer, added=10/12/1997, last-login:10/14/1997, total-logins:2, status:1]
%user:114 [ type=viewer, added=10/12/1997, last-login:10/14/1997, total-logins:1,
status:1]
%user:115 [ type=viewer, added=10/12/1997, last-login:10/12/1997, total-logins:1,
status:1
]
Ответ №1:
Вы можете использовать это регулярное выражение для поиска:
((?:^%|(?!A)G).*)R(?=[^][]*])
и замените его на:
$1
Обновленная демонстрация регулярных выражений
PHP-код:
$repl = preg_replace('/((?:^%|(?!A)G).*)R(?=[^][]*])/m', '$1', $str);
Подробности регулярного выражения:
(
: Запуск группы захвата # 1(?:^%|(?!A)G)
: Сопоставление%
в начале строки или перезапуск сопоставления с конца предыдущего сопоставления.G
утверждает позицию в конце предыдущего совпадения или в начале строки для первого совпадения..*
: Сопоставьте все в одной строке
)
: Завершить группу захвата # 1R
: Сопоставление любого символа новой строки(?=[^][]*])
: Убедитесь, что у нас есть]
ahead без сопоставления[
или]
между ними.
Комментарии:
1. Два небольших замечания…
]
похоже, что оно не соответствует вRegEx
демо и%user:113
вообще не соответствует… Это нормально?2. Оба желаемых поведения. 1.
]
не должен совпадать, потому что мы удаляем новую строку раньше]
. 2.%user:113
не соответствует, потому что он уже находится в одной строке.
Ответ №2:
Другой вариант — использовать вариант шаблона, который вы пробовали с отрицаемым символьным классом, для сопоставления %
и от открытия [
до закрытия ]
.
Затем для каждого соответствия удаляйте новые строки.
^%[^][]*[[^][]*]$
Объяснение
^
Начало строки%[^][]*
Сопоставьте%
и 0 раз с любым символом, отличным от[
или]
[[^][]*]
Сопоставление от[
до закрытия]
$
Утверждение конца строки
Демонстрация регулярных выражений | Демонстрация Php
Например
$result = preg_replace_callback("/^%[^][]*[[^][]*]$/m", function($m) {
return str_replace(PHP_EOL, "", $m[0]);
}, $data);
Ответ №3:
В качестве альтернативы регулярному выражению это просто разделяет данные с помощью ]
. Затем обрезает каждую строку и заменяет новые строки (используя PHP_EOL
) пробелом…
$output = explode("]", $data);
array_pop($output);
array_walk($output, function(amp;$data) {
$data = str_replace(PHP_EOL, " ", trim($data)."]");
});