Подтвердить что ты не робот

Можете ли вы спасти мой отрицательный пример lookbehind для присвоения чисел?

В главе "Расширенное регулярное выражение" в Освоение Perl, у меня есть разбитый пример, для которого я не могу найти хорошее исправление, Пример, возможно, пытается быть слишком умным для собственного блага, но, возможно, кто-то может исправить это для меня. В нем может быть свободная копия книги для исправления работы.:)

В разделе, посвященном поисковым запросам, я хотел использовать отрицательный lookbehind для реализации компиляции для чисел с дробными частями. Дело было в том, чтобы использовать негативный взгляд, потому что это была тема.

Я тупо сделал это:

$_ = '$1234.5678';
s/(?<!\.\d)(?<=\d)(?=(?:\d\d\d)+\b)/,/g;  # $1,234.5678

(?<!\.\d) утверждает, что бит перед (?=(?:\d\d\d)+\b) не является десятичной точкой и цифрой.

Глупое дело не слишком усложняется, чтобы сломать его. Добавляя еще одну цифру в конец, теперь существует группа из трех цифр, которой не предшествует десятичная точка и цифра:

$_ = '$1234.56789';
s/(?<!\.\d)(?<=\d)(?=(?:\d\d\d)+\b)/,/g;  # $1,234.56,789

Если lookbehinds может быть переменной шириной в Perl, это было бы очень просто. Но они не могут.

Обратите внимание, что это легко сделать без отрицательного lookbehind, но это не точка примера. Есть ли способ спасти этот пример?

4b9b3361

Ответ 1

Я не думаю, что это возможно без какой-либо формы с переменной шириной. Добавление утверждения \K в 5.10 дает возможность подделать позитивный внешний вид переменной ширины. Нам действительно нужен отрицательный внешний вид переменной ширины, но с небольшим творчеством и большим количеством уродства мы можем заставить его работать:

use 5.010;
$_ = '$1234567890.123456789';
s/(?<!\.)(?:\b|\G)\d+?\K(?=(?:\d\d\d)+\b)/,/g;
say;  # $1,234,567,890.123456789

Если когда-либо был шаблон, который просил обозначение /x, то это:

s/
  (?<!\.)        # Negative look-behind assertion; we don't want to match
                 # digits that come after the decimal point.

  (?:            # Begin a non-capturing group; the contents anchor the \d
                 # which follows so that the assertion above is applied at
                 # the correct position.

    \b           # Either a word boundary (the beginning of the number)...

    |            # or (because \b won't match at subsequent positions where
                 # a comma should go)...

    \G           # the position where the previous match left off.

  )              # End anchor grouping

  \d+?           # One or more digits, non-greedily so the match proceeds
                 # from left to right. A greedy match would proceed from
                 # right to left, the \G above wouldn't work, and only the
                 # rightmost comma would get placed.

  \K             # Keep the preceding stuff; used to fake variable-width
                 # look-behind

                 # <- This is what we match! (i.e. a position, no text)

  (?=            # Begin a positive look-ahead assertion

    (?:\d\d\d)+  # A multiple of three digits (3, 6, 9, etc.)

    \b           # A word (digit) boundary to anchor the triples at the
                 # end of the number.

  )              # End positive look-ahead assertion.
/,/xg;

Ответ 2

Если вам нужно публиковать в Qaru запрос, если кто-то может понять, как это сделать с отрицательным lookbehind, то это, очевидно, не является хорошим примером отрицательного lookbehind. Вам лучше подумать над новым примером, а не пытаться спасти этот.

В этом духе, как насчет автоматического корректора орфографии?

s/(?<![Cc])ei/ie/g; # Put I before E except after C

(Очевидно, что это не сложное и быстрое правило на английском языке, но я считаю это более реалистичным применением негативного внешнего вида.)

Ответ 3

Я не думаю, что это то, что вам нужно (особенно потому, что отрицательное утверждение выглядит отброшено), но, я думаю, ваш единственный вариант - разбить десятичные знаки, как в этом примере:

s/
  (?:
    (?<=\d)
    (?=(?:\d\d\d)+\b)
   |
    ( \d{0,3} \. \d+ )
  )
 / $1 ? $1 : ',' /exg;

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