正则表达式在tcl中的怪癖

ted*_*ted 9 regex tcl

这个问题是关于理解 Vivado中内置的TCL 8.5中特定正则表达式的行为,特别是在or两个正则表达式部分中我得到了意想不到的结果:

我致力于使用正则表达式缩进命令行的文本块.我的第一个想法是用缩进来替换每个newline用一个newline 一些spaces(X在这里为了清楚起见),所以:

puts [regsub -all "\n" "foo\nBar\nBaz" "\nXX"]
foo
XXBar
XXBaz
Run Code Online (Sandbox Code Playgroud)

这不会缩进第一行,以匹配我使用的第一行^:

puts [regsub -all "^" "foo\nBar\nBaz" "\nXX"]

XXfoo
Bar
Baz
Run Code Online (Sandbox Code Playgroud)

现在应该只是将两个正则表达式部分组合在一起|,但是我得到输出我无法解释:

puts [regsub -all "^|\n" "foo\nBar\nBaz" "\nXX"]

XXfoo
XX
XXBar
XX
XXBaz
Run Code Online (Sandbox Code Playgroud)

演示

附加新行和标识符(X)来自哪里?为什么看起来我有两次换人?这是一个错误,还是我对正则表达式语法有点不了解?

对于completnes来说,这是我现在使用的正则表达式 puts [regsub -all -line "^" "foo\nBar\nBaz" "XX"]

Bry*_*ley 3

基本正则表达式与扩展正则表达式

\n\n

我认为解释取决于这样一个事实:表达式^被视为基本正则表达式 (BRE),但是当您添加它时|,它会被视为高级正则表达式 (ARE),高级正则表达式 (ARE) 是扩展正则表达式 (ERE) 的超集。这是基于re_syntax 手册页中的以下内容:

\n\n
\n

ARE 是一个或多个分支,由 \xe2\x80\x9c|\xe2\x80\x9d 分隔,匹配与任何分支匹配的任何内容。

\n
\n\n

难题的第二部分是^在基本正则表达式和扩展/高级正则表达式中的处理方式不同。在基本正则表达式中,^仅当它是表达式的第一个字符时才具有特殊含义。再次,来自re_syntax 手册页

\n\n
\n

BRE 在几个方面与 ERE 不同... ^ 是一个普通字符,除了在 RE 开头或带括号的子表达式的开头之外,...

\n
\n\n

换句话说,对于 BRE,^将仅匹配字符串的开头,但在 ARE 中,它将匹配行的开头。

\n\n

那么,究竟发生了什么?

\n\n

首先,^匹配字符串的开头,因此它用 replacement 替换它\\nXX。接下来,它会看到f、then o、then o,没有一个匹配。然后它看到它匹配的 \'\\n`,因此它用替换项替换它。

\n\n

此时匹配器已经消耗了字符foo\\n。剩下的就是Bar\\nBaz。匹配器现在查看该字符串,并且模式^匹配,因此它再次用替换项替换它。因此,您最终会得到替换字符串的两份副本,一份用于换行符,一份用于保留字符串的开头。

\n\n

在每行的开头添加一些内容

\n\n

如果您的最终目标是为每一行添加缩进,则可以使用 regsub 进行换行敏感匹配,然后用于^匹配包括第一行在内的每一行,而不是尝试同时匹配换行符和字符串的开头。--line您可以通过将选项添加到 来完成此操作regsub。例如:

\n\n
regsub -line -all "^" "foo\\nBar\\nBaz" "XX" t; puts $t\n
Run Code Online (Sandbox Code Playgroud)\n