Помогите с регулярным выражением для проверки строки вида 159,5|15|19.6 и вытаскивания чисел

Всем добрый день! Уже мучаюсь около получаса, и не могу решить проблему

Есть строка вида 159,5|15|19.6

Требования:
— Количество чисел может быть любым
— Дробная часть числа может отделяться как точкой, так и запятой.
— Строка не должна содержать в начале и в конце символ "|" (т.е. должна начинаться и заканчиваться цифрами)
— Строка не должна содержать никаких лишних символов

У меня получилось следующее выражение, которое корректно находит все числа:
(?<=^|\d\|)(\d+(?:[\.,]\d)?)+(?=\|\d|$)

Но вот при попытке вставить символы начала или конца строки ^ и $ у меня ничего не выходит. Я делаю так:
^((?<=^|\d\|)(\d+(?:[\.,]\d)?)+(?=\|\d|$))+
но в таком случае, выражение находит только первое число, а на остальные не обращает внимания. Соответственно понятно, что если вписать в конце строки символ $, то ничего не будет найдено вообще.

Я пробовал кучу разных вариантов, но не буду захламлять ими вопрос. Я знаю, что я что-то недопонимаю в группировке, но что? Подскажите пожалуйста
  • Вопрос задан
  • 7666 просмотров
Пригласить эксперта
Ответы на вопрос 12
sledopit
@sledopit
$ echo -e "23561|783242|4823948.423847|47828374\n159,5|15|19.6\n253f|fjdk|fd32"| \
sed -r 's/^([0-9]+([,.][0-9]+){0,1}\|)+[0-9]+([,.][0-9]+){0,1}$/hi__&__bye/'

    hi__23561|783242|4823948.423847|47828374__bye
    hi__159,5|15|19.6__bye
    253f|fjdk|fd32

Ответ написан
@motl
^([0-9]+[.,]?[0-9]*\|)*([0-9]+[.,]?[0-9]*)$
Ответ написан
@motl
^([0-9]+)([.,]?)([0-9]*)$
Ответ написан
SLY_G
@SLY_G
журналист, переводчик, программист, стартапщик
Я бы сделал так:

while ($s =~ s/([\d,.]+)//) {
  print "$1\n";
}

Ответ написан
@motl
Sorry, here is the correct version:

^([0-9]+[.,]?[0-9]*\|)*([0-9])$/
Ответ написан
@motl
^([0-9]+[.,]?[0-9]*\|)*([0-9])$
Ответ написан
Комментировать
ualinker
@ualinker
^(?:\d+[,\.]?\d*\|)*(?:\d+[,\.]?\d*)+$
Пришлось продублировать шаблон нахождения числа, но я не вижу другого пути.
Ответ написан
@Yur4eg
(\d+(?:[.,]\d+)?(?:$|\|))+
Ответ написан
@fleshy
my $line = "159,5|15|19.6";
my @fields = split /\|/, $line;
for my $field (@fields) {
  is_valid_number($field);
}

is_valid_number() — соотв-но некая функция, которая проверяет, что переданная ей строка является числом. И не надо огород с регекспами городить там, где он не нужен
Ответ написан
@1099511627776
Пишу все что интересно и на всем на чем интересно
Я сомневаюсь, что эта задача будет иметь решение при помощи простого регекспа, в общем виде
Если наперед задать количество ' | ' тогда можно, или же использовать 2 варианты: split + (\d+)[,.](\d+)-для каждого из split-токенов.
Ответ написан
Комментировать
max7
@max7
max7
У меня получается два регэкспа. И для обеих задач их свести у меня не получается (псевдо javascript)

Задача получить числа:
var my_regexp = /(?:\||^)(\d+(?:[.,]?\d+)?)(?=\||$)/gi;

var my_str = "159,5|15|19.6|16|199,55|56.7";

var my_nums = [];

var ar;

while( (ar = my_regexp.exec(my_str)) != null )
{
   my_nums.push(ar[1]);
}

alert(my_nums);
 


Задача проверки:
var my_regexp = /^(?:(?:\||^)(\d+(?:[.,]?\d+)?)(?=\||$))+$/gi;

var my_str = "159,5|15|19.6|16|199,55|56.7";

alert(my_regexp.test(my_str));
 


Мне кажется, что свести их в один регэксп для двух операций не получится.
Ответ написан
Alukardd
@Alukardd
НУ влезу и я что ли с уже не кажущимся оригинальным вариантом:
printf '17.2|24|23,8' | gawk -v RS='|' -v 'i=0' '$0 !~ /^[0-9]+([.,][0-9]+)?$/{y=5}{x[i]=$0; i++}END{if(y!=5) for(j in x) print x[j]}'
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы