Как соотнести последовательные gsubs в ruby - PullRequest
0 голосов
/ 09 августа 2011

У меня есть следующее

address.gsub(/^\d*/, "").gsub(/\d*-?\d*$/, "").gsub(/\# ?\d*/,"")

Можно ли это сделать в одном gsub? Я хотел бы передать список шаблонов, а не только один шаблон - все они заменяются одним и тем же.

Ответы [ 3 ]

4 голосов
/ 09 августа 2011

Вы можете объединить их с оператором чередования (|):

address = '6 66-666 #99 11-23'
address.gsub(/^\d*|\d*-?\d*$|\# ?\d*/, "")
# " 66-666  "

address = 'pancakes 6 66-666 # pancakes #99 11-23'
address.gsub(/^\d*|\d*-?\d*$|\# ?\d*/,"")
# "pancakes 6 66-666 pancakes  "

Возможно, вы захотите добавить немного больше очистки пробелов. И вы можете захотеть переключиться на один из:

/\A\d*|\d*-?\d*\z|\# ?\d*/
/\A\d*|\d*-?\d*\Z|\# ?\d*/

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

3 голосов
/ 09 августа 2011

Объединение регулярных выражений - хорошая идея - и относительно простая - но я хотел бы рекомендовать некоторые дополнительные изменения.То есть:

address.gsub(/^\d+|\d+(?:-\d+)?$|\# *\d+/, "")

Из ваших исходных регулярных выражений ^\d* и \d*-?\d*$ будут всегда совпадать, потому что они не должны потреблять никаких символов.Таким образом, вы гарантированно выполняете две замены в каждой строке, даже если это просто замена пустых строк на пустые строки.Из моих регулярных выражений ^\d+ не потрудится сопоставить, если в начале строки не будет хотя бы одной цифры, а \d+(?:-\d+)?$ соответствует тому, что выглядит как выражение целого числа или диапазона в конце строки.

Ваш третий регулярное выражение, \# ?\d*, будет соответствовать любому символу #, и, если за # следует пробел и несколько цифр, он также примет их.Судя по вашим другим регулярным выражениям и моему опыту работы с другими вопросами, я подозреваю, что вы имели в виду совпадение #, только если за ним следует одна или более цифр, с дополнительными пробелами.Это то, что делает мой третий регулярное выражение.

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


РЕДАКТИРОВАТЬ (в ответ на комментарий): Работая с регулярными выражениями, вывсегда следует помнить о различии между регулярным выражением, которое не соответствует ничему , и регулярным выражением, которое не соответствует .Вы говорите, что применяете регулярные выражения к адресам улиц.Если адрес не начинается с номера дома, ^\d* не будет ничего совпадать, то есть он сообщит об успешном совпадении, причем указанное совпадение состоит из пустой строки, предшествующей первому символу в адресе.

Это не имеет значения, вы все равно просто заменяете его другой пустой строкой.Но зачем вообще делать замену?Если вы измените регулярное выражение на ^\d+, оно сообщит о неудачном совпадении, и замена не будет выполнена.Результат одинаков в любом случае, но сценарий «совпадение отметок» (^\d*) приводит к большой дополнительной работе, которую избегает сценарий «не соответствует».В ситуации с высокой пропускной способностью это может спасти жизнь.

Два других регулярных выражения приводят к дополнительным сложностям: \d*-?\d*$ может совпадать с дефисом в конце строки (например, "123-" или даже"-");и \# ?\d* может совпадать с символом хеша в любом месте строки, а не только как часть номера квартиры / офиса.Вы знаете свои данные, поэтому, вероятно, знаете, что ни одна из этих проблем никогда не возникнет;Я просто проверяю, что вы о них знаете.Мое регулярное выражение \d+(?:-\d+)?$ имеет дело с проблемой конечных дефисов, и \# *\d+ по крайней мере гарантирует, что после символа хеша есть цифры.

0 голосов
/ 09 августа 2011

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

Например, каждая из этих строк начинается сначало результата предыдущей
подстановки регулярных выражений.
s/^\d*//g
s/\d*-?\d*$//g
s/\# ?\d*//g

и это
s/^\d*|\d*-?\d*$|\# ?\d*//g
возобновляетсяпоиск / замена там, где последнее совпадение прекращено и потенциально может привести к другому общему выводу, особенно потому, что многие подвыражения ищут похожие
, если не совпадают символы, различающиеся только якорями строк.

Iдумаю, что ваши регулярные выражения достаточно уникальны в этом случае, и, конечно, изменение порядка
меняет результат.

...