这个问题是关于理解Vivado内置的TCL 8.5中特定正则表达式的行为,特别是or
- 两个正则表达式部分一起得到了意想不到的结果:
我致力于使用正则表达式缩进命令行的文本块。我的第一个想法是将每个newline
替换为newline
和一些spaces
(此处为X
替换为清晰度)以进行缩进,因此:
puts [regsub -all "\n" "foo\nBar\nBaz" "\nXX"]
foo
XXBar
XXBaz
这不会缩进第一行,以匹配我使用的第一行^
:
puts [regsub -all "^" "foo\nBar\nBaz" "\nXX"]
XXfoo
Bar
Baz
现在它应该只是用|
来组合两个正则表达式部分,但是我得到输出我无法解释:
puts [regsub -all "^|\n" "foo\nBar\nBaz" "\nXX"]
XXfoo
XX
XXBar
XX
XXBaz
附加换行符和标识符(X
)来自哪里?为什么看起来我有两次换人?这是一个错误,还是我对正则表达式语法有点不了解?
对于completnes来说,这是我现在使用的正则表达式puts [regsub -all -line "^" "foo\nBar\nBaz" "XX"]
答案 0 :(得分:3)
我认为解释取决于表达式^
被视为基本正则表达式(BRE)的事实,但是当您添加|
时,它被视为高级正则表达式(ARE) ,这是扩展正则表达式(ERE)的超集。这基于以下内容,来自re_syntax man page:
ARE是一个或多个分支,以“|”分隔,匹配任何与任何分支匹配的内容。
难题的第二部分是^
在基本和扩展/高级正则表达式中的区别对待。在基本正则表达式中,^
只有在表达式的第一个字符时才有特殊含义。同样,来自re_syntax man page:
BRE在几个方面与ERE不同... ^除了在RE的开头或带括号的子表达式的开头之外是一个普通的字符,...
换句话说,对于BRE,^
仅匹配字符串的开头,但在ARE中它将匹配行的开头。
那么,到底发生了什么?
首先,^
匹配字符串的开头,因此将其替换为替换\nXX
。接下来,它会看到f
,然后是o
,然后是o
,其中没有一个匹配。然后它会看到匹配的' \ n`,因此它将替换为替换。
此时,匹配器已使用了字符foo\n
。剩下的是Bar\nBaz
。匹配器现在查看该字符串,模式^
匹配,因此它再次替换为替换。因此,您最终得到了两个替换字符串的副本,一个用于换行符,另一个用于剩余字符串的开头。
如果你的最终目标是为每一行添加缩进,你可以使用与regsub的换行敏感匹配,然后使用^
匹配包括第一行的每一行,而不是尝试匹配新行和开头字符串。您可以通过向--line
添加regsub
选项来执行此操作。例如:
regsub -line -all "^" "foo\nBar\nBaz" "XX" t; puts $t