LINUX.ORG.RU

Задачка на регулярные выражения на Perl для изящного решения

 ,


0

1

Чего-то не могу сообразить как бы кратко и с помощью регулярных выражений сделать следующее:

Удалить из последовательности произвольной длины из точек и цифр последнюю точку и цифру. Если число одно - то вернуть пустую строку. Если не соответствует этому шаблону, то тоже пустую строку. Например,

1.2.3.115.95  - вернуть 1.2.3.115
27.4 - вернуть 27
6 - вернуть пустую строку ""
6.abcd.7.4 - вернуть пустую строку ""

Возникло на днях на практике. Долго думать было некогда и поскольку реально могли быть только варианты максимум с 4 цифрами просто ляпнул следующее:

sub parentcode
{
   my $s=$_[0]; 
   return $1 if ($s=~m/(\d+\.\d+\.\d+)\.\d+/g);
   return $1 if ($s=~m/(\d+\.\d+)\.\d+/g);
   return $1 if ($s=~m/(\d+)\.\d+/g);
   return "";
}

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

Может можно в одну строчку и регуляркой?

Update: в коментах нашлись варианты

★★★★★

Последнее исправление: praseodim (всего исправлений: 2)

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

sjinks Оно захватит не только цифры и точки.

Пожалуй добавлю в условие. Но наверное можно тогда две регулярки сделать - одна проверяет шаблон, другая возвращает, что надо. Интересно, можно одной обойтись?

praseodim ★★★★★
() автор топика
Последнее исправление: praseodim (всего исправлений: 3)
Ответ на: комментарий от crutch_master

Ну да, в общем, наверное так можно сказать, что есть ли способ указать повторители не для отдельного символа, а для шаблона? Ну типа (\.\d+)+

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

Хз насчёт шаблона, не видел такого. Учти, что оно может начать адово тормозить и лучше будет сделать сплит по точке, да проверить, чтобы всё было числами.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)

Может поможет (pwsh)

'1.2.3.4' -replace '(?<=^[\.0-9]+)?\.?\d+$'
# 1.2.3

'1' -replace '(?<=^[\.0-9]+)?\.?\d+$'
# пустая строка '^$'
anonymous
()
Ответ на: комментарий от sjinks

Хм, оказывается повторитель действительно можно для шаблона использовать. Вот даже не знал. Спасибо!

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

Не сразу понял, что у тебя тоже шаблон повторяется.

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

А можно небольшое пояснение? Я чего-то не совсем понял как это работает. Почему в m оказывается нужная длина?

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

? - это имя (в словаре или ассоц. массиве) сработавшей группы, потом можно вытаскивать с использованием $+{NAME}. Остальное сам

anonymous
()

Вместо матчинга всей строки можно же делать реплейс конца строки на пустое значение (без «домика» в начале регулярки), что-то типа: «/(?:\.?(?:0|[1-9][0-9]*))$/».

И обратите внимание на: «0|[1-9][0-9]*» вместо «\d+».

deep-purple ★★★★★
()

На шел проще, чем перловку напрягать.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.