2016-01-12 6 views
3

Im пытается получить следующий текстОтрицательный взгляд сзади нужен?

EDIT: второй $ ::/:: должен быть факультативным

when HTTP_REQUEST { 
    if { [matchclass ::USERAGENT contains $::XYZ ] or [matchclass $::USERAGENT contains $::ABC ] } { drop } 
    if { [matchclass $USERAGENT contains ::TEST ] } { drop } 
    if { [ matchclass $::useragent contains TEST ] } { drop } 
    return 
} 

посмотреть, как этот

when HTTP_REQUEST { 
    if { [matchclass ::USERAGENT contains XYZ ] or [matchclass $::USERAGENT contains ABC ] } { drop } 
    if { [matchclass $USERAGENT contains TEST ] } { drop } 
    if { [ matchclass $::useragent contains TEST ] } { drop } 
    return 
} 

т.е. удалить $:: или :: от слова рядом с \]

До сих пор у меня есть регулярное выражение,

re.sub(' \$?::(?=.*\])', ' ', text) 

Однако это производит,

when HTTP_REQUEST { 
    if { [matchclass USERAGENT contains XYZ ] or [matchclass USERAGENT contains ABC ] } { drop } 
    if { [matchclass $USERAGENT contains TEST ] } { drop } 
    if { [ matchclass useragent contains TEST ] } { drop } 
    return 
} 

Любые идеи? Также будет ли метод re использоваться для сопоставления, а не для замены. поиск/совпадение или поиск?

ответ

2

Вы должны заменить жадный шаблон соответствия точек на tempered greedy token:

\$?::(?=(?:(?!\$?::)[^\]])*\]) 
     ^^^^^^^^^^^^^^^^^^^ 

Это будет соответствовать $:: только если не последует $:: или :: до первого ].

  • (?:(?!\$?::)[^\]])* - ноль или более последовательностей ((?:...)*) ...
    • (?!\$?::)[^\]] - это не- ] символ ([^\]]), который не является отправной точкой для $:: или :: последовательности

Обратите внимание, что это регулярное выражение полезно использовать, если вы не уверены из чего может появляется после последнего $:: перед первым ]. В противном случае для вас должно работать регулярное выражение r" \$?::(?=\w+ *])".

См regex demo

Python code:

import re 
p = re.compile(r' \$?::(?=(?:(?!\$?::)[^\]])*\])') 
test_str = "when HTTP_REQUEST {\n if { [matchclass $::USERAGENT contains $::XYZ ] or [matchclass $::USERAGENT contains $::ABC ] } { drop }\n if { [matchclass $USERAGENT contains ::TEST ] } { drop }\n if { [ matchclass $::useragent contains $::TEST ] } { drop }\n return \n}\n\n" 
result = p.sub(" ", test_str) 
print(result) 
+0

Ваше регулярное выражение соответствует всем '$ ::'/'::' в квадратных скобках из-за жадных '. *'. Вам нужно ограничить его совпадением только с последним '$ ::'. Кстати, я бы не стал искать здесь, потому что lookbehind намного дороже, чем взгляды. –

+0

Кроме того, lookbehind проверяет известный контекст перед строкой, которую необходимо сопоставить. В вашем случае этот контекст неизвестен (судя по вашим другим комментариям). –

+0

Ваш ответ выглядит великолепно, но при тестировании он не работал, когда отсутствовал второй $ ::/::. т. е. вместо этого он удалил первый. Вопрос обновлен – felix001

1

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

$test = re.sub((r'\$?::(?=\w+\s*\])', '', $text); 

LOOKAHEAD (?=\w+\s*\]) найдет $:: или :: от слова рядом с ]

RegEx Demo

2

Поскольку слово contains (по крайней мере, в вашем примере) всегда прежде, вы также можете использовать:

re.sub('(?<=contains) *\$?::', ' ', x) 
1

Вы можете использовать 'назад, как ваши желаемые матчи предшествуют contains и сделать $ дополнительно:

(?<=contains)\$?::([A-Z]+) 

Посмотреть презентацию на regex101

+0

Ваш ответ выглядит великолепно, но при тестировании он не работал, когда отсутствовал второй $ ::/::. т. е. вместо этого он удалил первый. Вопрос обновлен. – felix001

+0

Кого вы подразумеваете под * вторым *? – Jan

+0

Второй $ :: или ::. Также может быть любой набор символов, а также слово, которое вы определяете как [A-Z], может быть любым набором символов – felix001

Смежные вопросы