Понимание регулярного выражения tcl glob?

set d(aa1) 1 
set d(aa2) 1                                                                                                                   
set d(aa3) 1
set d(aa4) 1
set d(aa5) 1
set d(aa6) 1
set d(aa7) 1
set d(aa8) 1
set d(aa9) 1
set d(aa10) 1
set d(aa11) 1
set regexp "a*\[1-9\]"
set res [array names d -glob $regexp]
puts "res = $res"

В этом случае результат:

res = aa11 aa6 aa2 aa7 aa3 aa8 aa4 aa9 aa5 aa1

Но при изменении регулярного выражения от a*\[1-9\] до a*\[1-10\] результаты становятся:

res = aa11 aa10 aa1

Ответы

Ответ 1

У вас есть ошибка в вашем классе символов.

  • [1-10] не означает цифру от 1 до 10
  • Это означает 1-1, который является символом от 1 до 1 (т.е. просто a 1) или 0. Это объясняет ваш результат.
  • чтобы выразить цифру от 1 до 10, используйте это: (?:10?|[2-9]) (как один из нескольких способов сделать это.
  • поэтому ваше регулярное выражение становится a*(?:10?|[2-9])
  • обратите внимание, что если ваш движок не позволяет не захватывать группу, вам нужно удалить ?:, для: a*(?:10?|[2-9])

Ответ 2

Вам нужно быть уверенным, что вы пытаетесь сопоставить, поскольку соответствие стиля glob и соответствие стиля regexp во многих аспектах различны.

Из документов, glob имеет следующее:

  • * соответствует любой последовательности символов в строке, включая пустую строку.
  • ? соответствует любому одиночному символу в строке.
  • [chars] соответствует любому символу в наборе, заданном символами. Если последовательность символов x-y появляется в символах, то любой символ между x и y, включительно, будет соответствовать. При использовании с -nocase конечные точки диапазона сначала преобразуются в нижний регистр. В то время как {[A-z]} соответствует _ при совпадении case-sensitively (поскольку _ находится между Z и a), при -nocase это считается как {[A-Za-z]} (и, вероятно, что означало в первом место).
  • \x соответствует одиночному символу x. Это дает возможность избежать специальной интерпретации символов *?[]\ в шаблоне.

Поскольку вы используете сопоставление стиля glob, ваше текущее выражение (a*\[1-9\]) соответствует a, за которым следуют любые символы и любой из 1 до 9 (это значит, что оно также будет соответствовать чему-то вроде abcjdne1).

Если вы хотите совместить хотя бы один a, за которым следуют цифры от 1 до 10, вам понадобится что-то вроде этого, используя режим -regexp:

set regexp {a+(?:[1-9]|10)}
set res [array names d -regexp $regexp]

Теперь, это регулярное выражение, я считаю более естественным для новичка ((?:[1-9]|10), означающее либо от 1 до 9, либо 10, но вы можете использовать форму, предложенную zx81 с (?:10?|[2-9]) значением 1, с необязательным 0 для 10 или от 2 до 9).

+ означает, что a должен появляться по крайней мере один раз для соответствия имени массива.

Если вам нужно сопоставить полные имена, вам нужно будет использовать привязки:

^a+(?:[1-9]|10)$

Примечание. Нельзя использовать сопоставление glob, если вы хотите совместить хотя бы один a, за которым следуют цифры, и чередование (используемый канал |) и квантификаторы (? или + или *) то, как они ведут себя в regexp, не поддерживаются сопоставлением glob.

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