#php #regex #perl #spam-prevention
#php #регулярное выражение #perl #предотвращение спама
Вопрос:
Я хотел бы использовать регулярное выражение Perl для сопоставления таких строк:
spaM
s p a m
sp Am
S p a m
Глядя на x
модификатор Perl, я должен быть в состоянии сделать это:
<?php
echo preg_match('#spam#ix', 's p a m');
?>
Но при этом выводится 0 (false). x
Модификатор фактически игнорирует пробелы в регулярном выражении, а не в анализируемой строке. Как бы я сделал это наоборот? То есть игнорировать пробелы в анализируемой строке, а не в моем регулярном выражении? Я знаю, что существуют многоэтапные способы сделать это, например, сначала удалить все пробелы из строки, но я хотел знать, существует ли мощное одноэтапное решение для регулярных выражений.
Ответ №1:
Честно говоря, я думаю, вам лучше убрать пробелы, чем сопоставлять. Поскольку это то, что вы собираетесь сделать, ваш код будет понятнее, чем поиск волшебного регулярного выражения или внедрение шаблонов пробелов между буквами.
Perl для этого тогда выглядел бы примерно так.
my $string = "S p A m";
(my $string_no_ws = $string) =~ s/s//g;
if ($string_no_ws =~ /spam/i) {
#do something
}
на самом деле вы можете выполнить тест без регулярного выражения, если хотите, используя index
:
my $string = "S p A m";
(my $lc_string_no_ws = lc $string) =~ s/s//g;
if (index($lc_string_no_ws, 'spam') >= 0) {
#do something
}
Комментарии:
1. Это и чище, и эффективнее, чем другие ответы.
Ответ №2:
#x
Модификатор работает наоборот. Это позволяет использовать посторонние пробелы в регулярном выражении, которые игнорируются при поиске:
preg_match('# s p a m #ix')
Будет соответствовать только «спаму».
Что вам нужно сделать, чтобы найти произвольный пробел в вашем регулярном выражении, так это вставить s*
между любыми буквами:
preg_match('# S s* P s* A s* M #ix', 's p a m');
Вы можете немного автоматизировать / упростить это, преобразовав слова в соответствующее регулярное выражение с перемешиванием s*
с помощью:
$regex = join('s*', str_split("spam", 1));
preg_match("#$regex#ix", "s p a m");
Комментарии:
1. Они должны изобрести что-то, чтобы сделать все это в регулярном выражении. В наши дни значительная часть веб-разработки направлена на борьбу со спамом.
2. @JoJo, Ведение списка спам-терминов и преобразований — это работа не механизма регулярных выражений, а модуля.
3. @JoJo, возможно, было бы проще удалить пробелы из строки, а не приспосабливать их к шаблону.
4. @ikegami: Это правда. Это также то, что делает mod_security (сначала нормализует / декодирует, затем проверяет). Однако зависит от контекста. Если вы также хотите проверить границы слов (в данном случае не уверены), то удаление пробела может нанести ущерб. (Однажды написал PHP-порт для рассылки спама. Здесь есть множество плюсов и минусов.)
Ответ №3:
/x
изменение для regex в perl относится к конструкции regex, а не к тому, что сопоставляется. Чтобы соответствовать имеющимся у вас значениям, вы хотите
/ss*ps*as*ms*/i
если порядок имеет значение для слова «спам», а если нет, то что-то вроде
/[spam tnr] /
было бы достаточно
Комментарии:
1. «maps», «spa», «sap» и так Далее Действительно не следует считать тем же словом, что и «спам»!
2. Ну, нет, это не так, отсюда различие «порядок не имеет значения»
3. Вы сказали » если порядок имеет значение» (курсив мой). Я указал, что порядок имеет значение.