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

时间:2013-12-12 12:33:10

标签: 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] 

如何避免此类案件并将不平衡的大括号视为一个词?

2 个答案:

答案 0 :(得分:1)

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

% 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的支撑部分的内容。

答案 1 :(得分:1)

当你有来自任意来源(如用户)的字符串时,根本不能保证它是一个结构良好的列表。现在regexp -inline返回匹配的列表,但该列表的元素是字符串(当然,除非你使用-indices选项),这意味着你不能安全地使用{{1在他们身上挑出碎片。

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

lindex

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

使用regexp -inline {\S+} $item将字符串分解为单词也是可能的,但是强烈假设单词分隔符是单个(默认为空格)字符,并且如果您有多个字符,则执行您可能不期望的操作-whitespace分隔符,或前导和尾随空格。坦率地说,将非空格分隔的字符串(例如,文件分为行,split记录到字段中)或将字符串转换为字符列表(使用空的第二个参数)更有用。