Выражение шаблона glob для шестнадцатеричного числа в TCL? - PullRequest
0 голосов
/ 04 августа 2020

Я пытаюсь понять разницу между шаблонами glob и regex. Мне нужно выполнить сопоставление с образцом в TCL.

Цель состоит в том, чтобы выяснить, введено ли шестнадцатеричное значение.

  1. Значение может начинаться или не начинаться с 0x
  2. Значение должно содержать от 1 до 12 шестнадцатеричных символов, т.е. 0-9, af, AF, и они должны следовать за 0x, если он существует

Дело в том, что glob не позволяет использовать {a, b}, чтобы указать, сколько символов нужно искать. Кроме того, при запуске я пытался использовать (0x [Xx])? но я думаю, что это не работает.

Не обязательно использовать glob. Я вижу, что между glob и regex есть тонкие различия. Я просто хочу знать, можно ли это сделать только с помощью регулярного выражения, а не с помощью glob.

Ответы [ 3 ]

3 голосов
/ 05 августа 2020

Дело в том, что glob не позволяет использовать {a, b}, чтобы сказать, сколько символов искать. Кроме того, при запуске я пытался использовать (0x [Xx])? но я думаю, что это не работает.

Обычно используемое регулярное выражение, не указывающее c на Tcl, - это ^(0[xX])?[A-Fa-f0-9]{1,12}$.

Обновление

Как пишет Донал, когда дело доходит до regexp, существует компромисс между стоимостью электроэнергии. Мне было любопытно, и для данных требований (необязательный префикс 0x, проверка диапазона [1,12]) я обнаружил, что тщательно созданный скрипт с использованием string операций, вкл. string match (см. isHex1 ниже) превосходит regexp в этой настройке (см. isHex2), независимо от случая ввода:

proc isHex1 {str min max} {
    set idx [string last "0x" $str]
    if {$idx > 0} {
      return 0
    } elseif {$idx == 0} {
      set str [string range $str 2 end]
    }
    set l [string length $str]
    expr {$l >= $min && $l <= $max && [string match -nocase [string repeat {[0-9a-f]} $l] $str]}
}

proc isHex2 {str min max} {
    set regex [format {^(0x)?[[:xdigit:]]{%d,%d}$} $min $max]
    regexp $regex $str
}

isHex1 расширяет идею вычисления string match шаблон на основе введенной длины (без префикса или без префикса) и string repeat. Мои собственные тайминги предполагают, что isHex1 работает как минимум на 40% быстрее, чем isHex2 (все с использованием time, 10000 итераций) в худшем случае (в пределах диапазона, решает последний символ). Другие случаи (например, выход за пределы допустимого диапазона) выполняются значительно быстрее.

2 голосов
/ 05 августа 2020

Шаблоны глобусов в Tcl намного проще, чем регулярные выражения. Все, что они поддерживают:

  1. * для обозначения любого числа любых символов.
  2. ? для обозначения любого отдельного символа.
  3. […] для означает любой одиночный символ из набора (символы в скобках, которые могут включать диапазоны).
  4. \x означает буквальный x (который может быть любым символом). Вот как вы помещаете метасимвол глобуса в шаблон глобуса.

Они также всегда привязаны к обоим концам. (Регулярные выражения намного мощнее. Они также медленнее. Вы платите за мощность.)

Чтобы сопоставить шестнадцатеричные числа, такие как 0xF00d, вы должны использовать такой шаблон глобуса:

0x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]

(или, как фактическая команда Tcl; мы помещаем образец в { фигурные скобки }, чтобы избежать необходимости использовать множество обратных косых черт для всех скобок ...)

string match {0x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]} $value

Обратите внимание, что у нас есть чтобы соответствовать точному количеству символов. (Вы можете сократить шаблон, используя сопоставление без учета регистра, до 0x[0-9a-f][0-9a-f][0-9a-f][0-9a-f].)

Сопоставление шестнадцатеричных чисел лучше выполнять с помощью regexp или scan (который также анализирует шестнадцатеричное число). Все любят забывать scan для парсинга, но у него неплохо получается ...

regexp {^0x([[:xdigit:]]+)$} $value -> theHexDigits
scan $value "0x%x" theParsedValue
2 голосов
/ 05 августа 2020

Синтаксис glob описан в документации string match. По сравнению с регулярными выражениями glob - грубый инструмент.

С регулярными выражениями вы получаете стандартные классы символов, включая [:xdigit:] для соответствия шестнадцатеричному di git.

В отличие от ответа mrcalvin, регулярное выражение c, специфичное для Tcl, будет выглядеть следующим образом: (?i)^0x[[:xdigit:]]{1,12}$

  • ведущий (?i) означает, что выражение будет сопоставляться без учета регистра.

Если все, что вас волнует, - это определить, является ли ввод допустимым число , вы можете использовать string is integer:

set s 0xdeadbeef
string is integer $s  ;# => 1

set s deadbeef
string is integer $s  ;# => 0

set s 0xdeadbeetle
string is integer $s  ;# => 0
...