Tcl 将不平衡大括号视为单词的正则表达式

Tcl 将不平衡大括号视为单词的正则表达式,tcl,Tcl,当行包含不平衡的大括号时,我在这个正则表达式中收到一条错误消息 set line "a b { c{}" set lst [regexp -all -inline {^(\s*(\S*)\s*)*(\{(.*)\})?(\s*(\S*)\s*)*$} $line] set lst [lindex $lst 0] set firstelement [lindex $lst 0] 如何避免这种情况并将不平衡的大括号视为一个单词?regexp命令返回一个列表。然后获取列表的第一个元素。但在最后一行

当行包含不平衡的大括号时,我在这个正则表达式中收到一条错误消息

set line "a b { c{}"
set lst [regexp -all -inline {^(\s*(\S*)\s*)*(\{(.*)\})?(\s*(\S*)\s*)*$} $line]
set lst [lindex $lst 0]
set firstelement [lindex $lst 0] 

如何避免这种情况并将不平衡的大括号视为一个单词?

regexp命令返回一个列表。然后获取列表的第一个元素。但在最后一行中,您将该元素视为一个列表-但不能保证是这样-因此实际的字符串内容很重要。相反,如果您想将此项目作为列表处理,则需要使用
拆分
并将其转换为文字:

% split "a b {" " "
a b \{
就你而言:

set lst [lindex $lst 0]
set firstelement [lindex [split $lst " "] 0]
您可能还需要查看
subst
。看起来您正试图将指定得不好的tcl列表作为输入读取,并进行一些解析以将它们作为正确的tcl列表。在这种情况下,
subst-nocommands[lindex$lst 0]
可能对您更有帮助。例如:

% lindex [subst -nocommands [lindex $lst 0]] 2
c{}

请注意,这是$line的大括号部分的内容。

如果您有来自任意源(如用户)的字符串,则无法保证它是格式良好的列表。现在
regexp-inline
返回匹配内容的列表,但该列表的元素是字符串(当然,除非您使用
-index
选项),这意味着您不能安全地在它们上使用
lindex
来挑选片段

假设您将“word”定义为“非空白字符序列”(通常的用户定义),获取第一个“word”的安全方法是:

set firstWord [lindex [regexp -all -inline {\S+} $item] 0]
这有点难看,但完全安全。(事实上,仅对于第一个单词,单独使用
regexp-inline{\S+}$item
,但这不会让您获得后面的单词。)


使用
split
将字符串拆分为单词也是可能的,但这强烈地假设单词分隔符是单个(默认为空白)字符,并且如果您有多个空格分隔符,或者前导和尾随空格,则可能会执行一些您不期望的操作。坦率地说,它更适用于将非空格分隔的字符串(例如,将文件划分为行,将
/etc/passwd
记录划分为字段)或将字符串转换为字符列表(第二个参数为空)。

subst究竟有何帮助?