LINUX.ORG.RU

Как ограничить пост-проверку (lookbehind)?

 ,


0

1

Касается ТОЛЬКО grep. Интересно само регулярное выражение с perl-синтаксисом.

Например мне надо вытащить значение из строки, выводимой lspci:

00:02.0 VGA compatible controller: Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics] (rev 03)

Надо получить:

Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics]

В pwsh работает:

# Select-String

$ (lspci | sls '(?<=VGA.+\:\s).+(?=\s\(.+)').Matches.Value
Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics]

Но grep хочет уточненных данных, его смущает .+
Т.к. разбор идет справа налево, он не успевает дойти до ключевого слова VGA

$ lspci | grep -Po '(?<=VGA.+\:\s).+(?=\s\(.+)'
/usr/bin/grep: length of lookbehind assertion is not limited

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

$ lspci | grep 'VGA' | grep -Po '(?<=:\s).+(?=\s\(.+)'
Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics]

Это просто пример, никакого практического значения он не имеет, только ради понимания.

★★★★★
Ответ на: комментарий от dmitry237

Ну, про VGA ты тоже не знаешь, но грепаешь. Вдруг попадётся система с EGA compatible controller? Что там ещё может быть, кроме «compatible controller»?

Для себя я проблему с грепами, авками, седами решил давно: перл их заруливает. Правда, look behind перл тоже ограничивает, но в случае с перлом look behind можно не испльзовать:

$ lspci | perl -ne '/(?:VGA[^:]*: )(.*)/ && print $1'
Advanced Micro Devices, Inc. [AMD/ATI] Baffin [Radeon RX 550 640SP / RX 560/560X] (rev cf)
debugger ★★★★★
()

Если уж надо именно греп, то ограничить look behind можно вот так:

$ lspci | grep -Po -e '(?<=VGA.{,100}: ).*'
Advanced Micro Devices, Inc. [AMD/ATI] Baffin [Radeon RX 550 640SP / RX 560/560X] (rev cf)
debugger ★★★★★
()
Последнее исправление: debugger (всего исправлений: 1)
Ответ на: комментарий от dmitry237

При том, что перед двоеточием — подкласс устройства, коих ограниченное количество. Например, контроллеров дисплея есть ровно четыре штуки: VGA compatible controller, XGA compatible controller, 3D controller, Display controller. Если ты, например, хочешь выделить из вывода lspci контроллер дисплея, то стоит искать ([VX]GA compatible|3D|Display) controller, а не просто VGA. А если тебя интрересует именно VGA compatible controller, то стоит искать VGA compatible controller, а не VGA. Искать слово VGA не стоит, можно поймать VGA compatible unclassified device. И да, VGA — всего лишь пример.

debugger ★★★★★
()
Ответ на: комментарий от dmitry237

В перле — да:

Prior to Perl 5.30, it worked only for fixed-width lookbehind, but starting in that release, it can handle variable lengths from 1 to 255 characters as an experimental feature.
https://perldoc.perl.org/perlre

Что там в PCRE (который используется в грепе) — не знаю.

debugger ★★★★★
()
Последнее исправление: debugger (всего исправлений: 1)
Ответ на: комментарий от iron

Меня интересовала именно ретроспективная проверка, как элемент регулярного выражения.

Я вот не знал, что синтаксис perl допускается только 255 символов:

echo "aaa bbb" | grep -Po '(?<=.{,254}\s).+'

Это задача просто для понимания, как сравнение с синтаксисом из dotnet семейства, где такого ограничения нет. Я не мог понять почему grep выдает ошибку.

dmitry237 ★★★★★
() автор топика
Ответ на: комментарий от dmitry237

если используется Perl-совместимый, он же PCRE, то у него просмотр назад используется только чётко заданной длины, то есть 5 точек он назад просмотрит методом сдвига указателя (сложением указателя и смещения), а плавающий вариант не работает, то есть (?<=.+?) где длина не задана явно, то это работать не будет. Как вариант использовать \K, это будет идти до \K и откинет всё что до \K, то есть аналог (?<=….) с не явно заданной длиной, но он не просматривает назад, он изначально идёт вперёд проверяя совпадение до \K как обычное регулярное выражение. Просто просмотр назад по факту делается позже и может захватить больше результатов, а \K не даст возвратится назад и смотрит только следующие полные совпадения.

AZJIO
()