2016-06-20 3 views
2

Мне кажется, что я ударился головой о кирпичную стену.PHP Regex - соответствие одной из групп символов, когда одна из групп символов не находится в строке

У меня есть строка, которая выглядит следующим образом:

$record['filenameGood'] = '49161_Comma_Dataphoria-Clickwork7Export{DATE:dmY}'; 

И я хочу, чтобы блокировать имена файлов, которые содержат какие-либо недопустимые символы.

Однако ... Я использую заполнитель для текущей даты, которая выглядит как {DATE:Y-m-d} где Y-m-d бы получить вставленную в php сек date функции. Эта часть, в которой я в порядке, это просто обеспечение того, чтобы остальная часть строки не содержала ограниченный символ.

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

// Matches one of " * : % $/\ ' ? 
$patternOne = '#["*:%$/\\\'?]#'; 

// Desired: matches one of " * : % $/\ ' ?, but ALLOWS {DATE:.*?} 
$patternTwo = '#["*:%$/\\\'?]#'; 
$record = []; 
$record['filenameGood'] = '49161_Comma_Dataphoria-Clickwork7Export{DATE:dmY}'; 
$record['filenameBad'] = '49161_Comma_Dataphoria-Clickwork7:Export{DATE:dmY}'; 

var_dump(preg_match($patternTwo, $record['filenameGood'])); 
var_dump(preg_match($patternTwo, $record['filenameBad'])); 

Текущий выход:

int(1) 
int(1) 

В то время как мой желаемый результат является:

int(0) // Good string, contains : within {DATE:} 
int(1) // Bad string, contains a : NOT within {DATE:} 

мне нужен строка, подобная следующей, чтобы получить соответствие:

'49161_Comma_Dataphoria-Clickwork7Export{DATE:d:m:Y}' 

Надеюсь, я объяснил это достаточно хорошо, чтобы вы поняли!

+0

Вы пытались сначала разрешить местозаполнитель, а затем проверить его? –

+1

Некоторая неясная магия с использованием '(* SKIP) (* FAIL)': ['{DATE: [^}] *} (* SKIP) (* FAIL) | [" *:% $ ​​/ \\\ '?] ' ] (https://regex101.com/r/pW4pO5/1). [Explanation here] (http://stackoverflow.com/questions/24534782/how-do-skip-or-f-work-on-regex) – HamZa

+1

@HamZa Спасибо за ваш ответ. Это невероятно близко к тому, что мне нужно. Все, что мне нужно было сделать, чтобы заставить его работать, это добавить мой список отвергнутых символов в класс отрицательных символов в начале: '{DATE: [^} "*:% $ ​​/ \\\ '?] *} (* SKIP) (* FAIL) | [" *:% $ ​​/ \\\'?] '. Добавьте это как ответ, и я с радостью его приму –

ответ

2

Вы можете использовать отрицательный после просмотра назад класс символов:

$patternTwo = '#["*:%$/\\\\\'?](?<!{DATE:)#'; 
           ^^^^^^^^^^^ 

ВИДЕТЬ IDEONE demo.

Здесь один из символов класса символов сопоставляется первым, но затем отрицательный lookbehind будет проверять, не стоит ли :{DATE. Если это так, результат будет неудачным.

+0

Спасибо за ваш ответ! Я в конечном итоге отметил это как верный комментарий, предоставленный @HamZa, из-за того, что мне приходилось включать только мои ограниченные символы. Спасибо за помощь! –

+2

Обратите внимание, что вам нужно 4 обратных слэша, чтобы они соответствовали буквальная обратная косая черта с одноосевым регулярным выражением PHP, я исправил это только сейчас. И я согласен, что метод '(* SKIP) (* F)' весьма удобен в этих сценариях. Я также удалил ненужный '\ b', так как он запросил букву слова перед' {'. –