2016-06-13 8 views
0

Как выполнить синтаксический анализ символа обратной косой черты в tcl?разбор обратной косой черты () символ в tcl

У меня есть шаблон со значением «\Q[9]_i_1_n_0» и я хочу найти строку $line, содержащую этот шаблон? Как я мог это сделать?

(puts $pattern возвращается: {\Q[9]_i_1_n_0} но я использую foreach j [split $pattern] петлю, так что $j чисто \Q[9]_i_1_n_0)

regexp $pattern $pattern 

не работает:

Error: couldn't compile regular expression pattern: invalid escape \ sequence 

lsearch $pattern $pattern возвращает -1

string match $pattern $pattern возвращает 0 .

regexp {$pattern} $pattern возвращение 0

+0

Вы пробовали двойную обратную косую черту '\\\'? –

+0

http://stackoverflow.com/questions/19495405/tcl-backslash-issue-regsub –

ответ

0
set pattern {\Q[9]_i_1_n_0} 

string first $pattern $pattern 
# => 0 

Matching с string first сравнивает текстовое содержимое обеих строк без присвоения каких-либо особое значение символов. Результат 0 означает, что совпадение было найдено в позиции 0 (если нет совпадения, вы получаете -1). string first не скажет вам, если вы нашли точное соответствие: для этого вам нужно убедиться, что результат равен 0, а длина строк одинакова.

Соответствие по «glob-style»/«string match» или регулярному выражению должно учитывать символы, которые являются особыми для соответствующих языков. Например, \, *, ?, [, ] специальные в согласовании Glob стиле, и \, ., *, +, ?, {, }, (, ), ^, $ специальные в регулярных выражений. «Особый» в этом контексте означает, что, например, \ не означает «обратную косую черту», ​​но (в обоих случаях) «побег», то есть символ, который отнимает «специальность» другого персонажа. Это означает, что, например, \\ означает обратную косую черту, а \* означает звездочку.

Поскольку шаблон вы используете содержит как \, [ и ], они должны быть экранированы до шаблон может быть использован для Glob-стиля или соответствия регулярных выражений. (На самом деле, по синтаксической причуде, ], которая закрывает сбежавший [ не нужно экранировать.)

Один из самых простых способов, чтобы избежать этих символов с помощью операции перевода строки выполняется командой string map. Можно было бы подумать, что это будет делать трюк:

string map {\ \\ [ \[} $pattern ;# error! this code won't work! 

, но это не будет работать, так как обратные косые все еще особенные в команде string map.Мы должны точно удвоить количество слеша карты:

string map {\\ \\\\ [ \\[} $pattern 

и теперь мы можем попытаться использовать сопоставление Глобо-стиль/регулярное выражение:

string match [string map {\\ \\\\ [ \\[} $pattern] $pattern 
# => 1 
regexp [string map {\\ \\\\ [ \\[} $pattern] $pattern 
# => 1 

Результат 1 означает булево истину: а матч найден. Обратите внимание, что результаты будут отличаться, если есть префикс и/или суффикс:

string match [string map {\\ \\\\ [ \\[} $pattern] abc${pattern}def 
# => 0 
regexp [string map {\\ \\\\ [ \\[} $pattern] abc${pattern}def 
# => 1 

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

Соответствие в списке аналогично. lsearch -exact работает как string first, за исключением того, что он будет принимать ровно равные строки. lsearch -regexp и lsearch -glob работают как регулярное выражение и совпадение в стиле glob, соответственно.

set list [concat abc $pattern def] 
# => abc \Q[9]_i_1_n_0 def 
lsearch -exact $list [join $pattern] 
# => 1 
lsearch -regexp $list [string map {\\ \\\\ [ \\[} [join $pattern]] 
# => 1 
lsearch -glob $list [string map {\\ \\\\ [ \\[} [join $pattern]] 
# => 1 

Результат 1 здесь означает, что второй элемент в списке (индекс 1) соответствует шаблону.

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

Документация: concat, join, lsearch, Syntax of Tcl regular expressions, regexp, string

+0

@ user2921643: Я немного испортил сопоставление элементов списка. Я обновил ответ. –

0

У вас есть строка с несколькими символами в ней, которые являются метасимволами для regexp и string match. В частности, обе интерпретируют обратную косую черту и скобки, чтобы означать вещи по умолчанию. Это означает, что lsearch не найдет его (или lsearch -glob), что lsearch -regexp не будет работать (недействительный RE), и lsearch -exact найдет его только в том случае, если это была целая строка (нет точек для частичного совпадения с этой опцией lsearch).

Но вы можете переопределить поведение regexp -style согласования, поставив ***= в передней части рисунка, при условии вы ищете буквальный:

set sampleText {this is a sample \Q[9]_i_1_n_0 with the pattern in it} 
set pattern {\Q[9]_i_1_n_0} 
puts [regexp ***=$pattern $sampleText] 
# Prints 1... it matched! 

Давайте получить лучшее соответствие информации:

puts [regexp -inline -indices ***=$pattern $sampleText] 
# {17 29} 

Похоже, что я прав. Это также будет работать с lsearch -regexp; трюк ***= является особенностью ядра ядра RE (который является общим).

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