Увеличьте все числа, кроме одного или нескольких (разделенных запятыми), условно на предыдущую строку (и) (для индекса книги) - PullRequest
2 голосов
/ 15 октября 2019

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

Adam undЕва 42–44 (абб. 14, 15)

Библиотека Апостолическая Ватикана Код. грамм1613 31 31 (Сокр. 8)

Гамбург, Staatsbibliothek Ms. 151 в скрин. 35 (абб. 11)

Transverberation der Hl. Тереза ​​фон Авила 10, 18 (абб. 2, деталь S. 8)

Файл содержит цифры для годов, цифр и т. Д. Однако номера страниц

  • никогда не бываютперед "Abb." или "Ms."
  • имеют 3 цифры или меньше

Я хотел бы добавить число 4 к номерам страницы, в идеале приводя к

Адам и Ева 46–48 (абб. 14, 15)

Библиотека Апостолическая Ватиканская треска. грамм1613 35 35 (Сокр. 8)

Гамбург, Staatsbibliothek Ms. 151 в скрин. 39 (абб. 11)

Transverberation der Hl. Theresa von Avila 14, 22 (Abb. 2, Detail S. 12)

Устное правило может быть таким: Добавить 4 к каждому числу, если оно имеет 3 цифры или меньше и если ему не предшествует«Abb. | Ms.» Или другое число, которое отделено от «,» и, в свою очередь, предшествует «Abb. | Ms.»

Следующая строка

perl -pe 's/(?<!Abb. )(\b\d{1,3}\b)/$1+4/eg' original.md

производит

Adam und Eva 46--48 (Abb. 14, 19)
Biblioteca Apostolica Vaticana Cod. gr. 1613 35 35 (Abb. 8)
Hamburg, Staatsbibliothek Ms. 155 in scrin. 39 (Abb. 11)
Transverberation der Hl. Theresa von Ávila 14, 22 (Abb. 2, Detail S. 12)

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

  1. Число второй цифры в строке 1, конечно, увеличилось на 4. Но я незнаю, как это исправить. Я знаю, что я мог бы расширить среднюю часть до чего-то вроде (\b\d{1,3}\b),?\s?(\b\d{1,3}\b)? и сослаться на второе число с $2, но я не знаю, как обращаться с разделительной запятой (если она существует) в замене.
  2. Число после "Ms." увеличилось на 4. Но если я изменю негативный взгляд на (?<!(Abb. |Ms. )), я получу ошибку Variable length lookbehind not implemented in regex m/(?<!(Abb. |Ms. ))(\b\d{1,3}\b)/ at -e line 1. Я не знаю альтернативы такой реализации.

Буду признателен за любую помощь по этим двум проблемам!

1 Ответ

2 голосов
/ 15 октября 2019

Вы можете использовать следующее регулярное выражение:

Смотрите здесь используемое регулярное выражение

(?:Abb|Ms)\.\s+\d{1,3}(?:,\s+\d{1,3}\b)*(*SKIP)(*FAIL)|\b\d{1,3}\b

Это регулярное выражение работает следующим образом:

  • (?:Abb|Ms) Соответствует либо Abb, либо Ms буквально
  • \.\s+ Соответствует буквальному символу ., за которым следует один или несколько пробельных символов.
  • \d{1,3}Совпадение от 1 до 3 цифр
  • (?:,\s+\d{1,3}\b)* Сопоставление следующей группе без захвата любое количество раз:
    • ,\s+\d{1,3}\b Совпадение ,, за которым следует пробельный символ один или несколько раззатем от 1 до 3 цифр и утверждают конец цифры, используя границу слова
  • (*SKIP) управляющий глагол, который заставляет регулярное выражение отказаться от текущего соответствия, если оно пытаетсяоткат назад после своей позиции (это означает, что он действительно соответствует этой строке и будет препятствовать сопоставлению второй опции)
  • (*FAIL) управляющий глагол, который вынуждает это совпадение завершиться неудачно, что приводит к исключению текущего совпадения из результатов

Второй вариант - это то, чтоt фактически соответствует: \b\d{1,3}\b - соответствует от 1 до 3 цифр, утверждая каждую сторону как границу слова.


Если \b не соответствует должным образом каждой позиции, вы можете заменить \b с (?:(?<=\D)|^) для предшествующего и (?=\D|$) для исходящих границ слов соответственно:

Смотрите здесь регулярное выражение

(?:Abb|Ms)\.\s+\d{1,3}(?:,\s+\d{1,3}(?=\D|$))*(*SKIP)(*FAIL)|(?:(?<=\D)|^)\d{1,3}(?=\D|$)

Эти взгляды назад / взгляды работают путем утвержденияв предыдущей / следующей позиции существует либо нецифровой символ, либо привязка к началу / концу строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...