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