Как заменить определенное количество пробелов с помощью регулярных выражений? - PullRequest
3 голосов
/ 01 марта 2012

Я использую Caliber для преобразования PDF в MOBI, но у него возникают проблемы при интерпретации блоков кода с пробелами.Блоки содержат много пробелов, но в разных количествах.Некоторые строки даже имеют отступ в 31 пробел.

Калибр позволяет 3 регулярным выражениям выполнять поиск и замену в книге до ее преобразования.

Это то, что я пробовал.

\n( *) ( *)([a-zA-Z{};\*\/\(\)&#0-9])

Заменить на:

\n\1 \2\3

Проблема, он заменяет только один из пробелов.Я хочу, чтобы все они были заменены одинаковым количеством  .

Я также пробовал ленивые версии первой группы и т. Д.

Это один из случаев, когда регулярных выражений недостаточно?Я думаю, что это регулярное выражение является стандартом Python.

Ответы [ 3 ]

2 голосов
/ 01 марта 2012

Если бы это был Perl, вы могли бы заменить (\G|\n) на $1&nbsp;, и если бы это был механизм регулярных выражений, который позволял смотреть за пределами ограниченной ширины (вместо просмотра за фиксированной шириной как у Python), вы могли бы заменить (?<=\n {0,30}) на &nbsp;; но, как есть, единственный способ, которым я могу придумать, - это заменить что-то вроде ((?<=\n)|(?<=\n )|(?<=\n {2})|(?<=\n {3})|(?<=\n {4})|(?<=\n {5})|...|(?<=\n {30})) на &nbsp;. , , и я подозреваю, что в этот момент вы достигнете предела того, как долго Caliber позволяет вводить регулярные выражения. : - /

Другой вариант - использовать совершенно другой подход и заменить (два пробела) на &nbsp; (неразрывный пробел + регулярный пробел), не удосуживаясь ограничить его началом строки. Я предполагаю, что это удовлетворит ваши потребности?

1 голос
/ 01 марта 2012

Есть ли причина не просто заменить ВСЕ пробелы неразрывными? (r/ /&nbsp;/).

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


Ради забавы, моя попытка в Python:

>>> eight_spaces = "        hello world!"
>>> re.sub(r"^(|(?:&nbsp;)*)\s",r"\1&nbsp;",eight_spaces)
'&nbsp;      hello world!'

Идея заключается в замене одного пробела за раз. Он не работает, потому что движок re не возвращается к началу строки после совпадения - он потребляет строку, работающую слева направо.

Обратите внимание на чередование (?:&nbsp;)* с пустой строкой (|(?:&nbsp;)*), так что группа захвата \1 всегда захватывает что-то (даже пустую строку.)

1 голос
/ 01 марта 2012

\ s {31} будет соответствовать ровно 31 пробелу, \ s {14,31} от 14 до 31

...