При использовании совпадения строк требуется ли экранировать специальные символы? - PullRequest
3 голосов
/ 07 февраля 2012

Я работаю над сценарием для анализа определенного кода ошибки из сообщения SOAP с использованием tcl, и я наконец пришел к той части, где я сравниваю сообщение с нужным сообщением. Как видите, я пытаюсь проверить, содержится ли строка «9000» в элементе массива «$ soap (Fault)»


if { [ string match *\<FaultCode\>9000\</FaultCode\>* $soap(Fault) ] } {

    # -- Success case

} else {

    # -- fail case

}

В приведенном мною примере я избежал всех "специальных символов" в tcl:

&;`'"|*?~<>^()[]{}$\

но требуется ли это? Можно ли просто сделать:

*<FaultCode>9000</FaultCode>*  ?

Я довольно тщательно осмотрелся и не смог найти что-то столь же точное, как то, о чем я спрашиваю. Я собирался спросить в чате tcl, но я не смог его найти!

Спасибо

Ответы [ 4 ]

4 голосов
/ 07 февраля 2012

Короткий ответ: нет, вам не нужно экранировать всех этих символов.На самом деле, некоторые из этих символов даже не являются специальными.

Здесь есть два слоя: во-первых, на уровне синтаксического анализа tcl: чтение правил синтаксического анализа tcl , у вас есть несколько вариантов:

  • Заключите аргумент в двойные кавычки.(но тогда вам нужно беспокоиться о встроенных кавычках, [командах] и $ переменных)
  • Оберните ваш аргумент в фигурные скобки.(но тогда вам нужно беспокоиться о вложенных скобках)
  • Используйте простое слово, как у вас выше (но тогда вам нужно беспокоиться о начальных скобках, кавычках, пробелах и обо всем, что касается двойных кавычек, выше).

Все это просто определяет, что передается в [соответствие строки] - второй уровень включает в себя, как [соответствие строки] работает с этим шаблоном (это не регулярное выражение, кстати, это просто шаблон в стиле глобуса ).В шаблонах стилей глобуса tcl есть только эти специальные символы: *,?, [],.Если вы хотите, чтобы любой из них считался литералом, вы должны избежать его.Все остальное рассматривается как буквальное совпадение, поэтому вам не нужно беспокоиться о <> или о /.

Итак, эта строка в порядке:

string match *<FaultCode>9000</FaultCode>* $soap(Fault)

Но вы также можете использовать эти стили, чтобы стилистически выделить шаблон соответствия.

string match "*<FaultCode>9000</FaultCode>*" $soap(Fault)
string match {*<FaultCode>9000</FaultCode>*} $soap(Fault)
2 голосов
/ 07 февраля 2012

Для string match единственными специальными символами являются [, \ , ? и * - http://www.tcl.tk/man/tcl8.5/TclCmd/string.htm#M40

Для парсера Tcl в общем, да, есть еще несколько вещей, о которых вы должны подумать - http://www.tcl.tk/man/tcl8.5/TclCmd/Tcl.htm

1 голос
/ 08 февраля 2012

Другой (и более простой IMO) подход заключается в том, чтобы просто искать в строке наличие заданной подстроки и посмотреть, был ли поиск успешным, например:

set found [expr {[string first $needle $haystack] >= 0}]

Это простой поиск, ни одна из строк не интерпретируется каким-либо образом, поэтому не стоит беспокоиться по поводу побега.

Другими словами, ваша конкретная потребность слишком проста, чтобы бросать в нее инструменты, предназначенные для более тяжелого подъема. Например, вы хотите использовать регулярное выражение или сопоставление с глобусом, если вам нужно искать, скажем, «подстроку, начинающуюся с <FaultCode>, затем содержащую набор смежных символов в диапазоне от 0 до 9 и оканчивающийся на </FaultCode> "- это будет, в частности, механизмом регулярных выражений, позволяющий извлекать эту неопределенную подстроку цифровых символов из строки.

Кроме того, я чувствую, что должен делать примечание обязательным в случаях, подобных этому: не разумно анализировать XML ни с чем, кроме инструментов XML. В частности, существуют tclsoap и tdom .

0 голосов
/ 07 февраля 2012

Отказ от ответственности: я не знаю TCL, только регулярные выражения

Очевидно, , в TCL рекомендуется окружать ваше регулярное выражение двойными кавычками "regex" или фигурными скобками {regex} - тогда вам не нужно беспокоиться о том, чтобы избежать того, что не является зарезервированным символом регулярного выражения .

Я почти уверен, что < и > не нужно экранировать.

Я не знал, что * можно использовать в качестве окружающих предметов - это зарезервированный символ регулярного выражения. Учитывая это, я рекомендую сделать это вместо: {<FaultCode>9000</FaultCode>}

...