1

我在 TCL 中有以下代码:

"\\*05.|__|##|.T|__|__|"

试图匹配以下输出:

*05 |__|##| T|__|__|

它匹配。

但如果输出是:

*05 |__|##|__|__|__|

它也匹配,有什么问题,以及如何解决?

4

1 回答 1

8

该字符|是一个特殊字符,用于表示正则表达式中的“或”。你需要做的是逃避它。

"\\*05.\\|__\\|##\\|.T\\|__\\|__\\|"

现在,为了避免所有这些双重转义,只需使用大括号!

regexp {\*05.\|__\|##\|.T\|__\|__\|} $string

解释

如果你想要更深入的解释,你应该问。我不咬人!xD

当您使用:

regexp "\\*05.|__|##|.T|__|__|" "*05 |__|##| T|__|__|"

Tcl 正在调用命令regexp并且首先评估表达式(它在被带到实际命令之前首先被处理,regexp并且发送到regexp的是:

\*05.|__|##|.T|__|__|

现在,由于|meanin regexp,该命令会将其评估为:

  • 一个文字字符*,然后05是 ,然后是任何一个字符(换行符除外),或

  • _,或

  • #,或

  • 后跟的任何字符T,或

  • _,或

  • _,或

  • 没有

然后它将上面的每一个与你想要匹配的字符串进行比较,*05 |__|##| T|__|__|.

第1步:*05.字符串中有吗?是的,“*05”在字符串中,因此匹配,所以它返回 1。

当您将其与 进行比较时*05 |__|##|__|__|__|,会发生同样的事情:

第1步:*05.字符串中有吗?是的,“*05”在字符串中,因此匹配,所以它返回 1。


修复

使用双重转义,在任何评估后进入正则表达式的字符串是:

\*05.\|__\|##\|.T\|__\|__\|

然后正则表达式将其读取为:

一个文字*字符,然后05是任何字符,然后是文字|,二_,文字|,二#,文字|,任何字符,a T,文字|,二_,文字|,二_和文字|

只有一个选项,因此当它与 比较时*05 |__|##| T|__|__|,它匹配。

当它将它与 比较时*05 |__|##|__|__|__|,当正则表达式将检查时T,它不会找到匹配项。


牙套有什么作用?

大括号防止在将表达式发送到正则表达式过程之前对其求值。因此,表达式将保持与您输入的相同。如果你放:

{\\*05.\\|__\\|##\\|.T\\|__\\|__\\|}

正则表达式将接收\\*05.\\|__\\|##\\|.T\\|__\\|__\\|并解释为\0 次或多次,然后05是 ,然后是任何字符,a \,OR 等......

这就是为什么你不用大括号双重转义:

{\*05.\|__\|##\|.T\|__\|__\|}

regexp 将收到的表达式是\*05.\|__\|##\|.T\|__\|__\|,这是您在"\\*05.\\|__\\|##\\|.T\\|__\\|__\\|"之前处理过之后的表达式。

于 2013-08-08T16:13:06.863 回答