如何在Tcl中修复以下正则表达式?

use*_*316 1 regex tcl

我在TCL中有以下代码:

"\\*05.|__|##|.T|__|__|"
Run Code Online (Sandbox Code Playgroud)

尝试匹配以下输出:

*05 |__|##| T|__|__|
Run Code Online (Sandbox Code Playgroud)

它匹配.

但如果输出是:

*05 |__|##|__|__|__|
Run Code Online (Sandbox Code Playgroud)

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

Jer*_*rry 8

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

"\\*05.\\|__\\|##\\|.T\\|__\\|__\\|"
Run Code Online (Sandbox Code Playgroud)

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

regexp {\*05.\|__\|##\|.T\|__\|__\|} $string
Run Code Online (Sandbox Code Playgroud)

说明

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

当你使用:

regexp "\\*05.|__|##|.T|__|__|" "*05 |__|##| T|__|__|"
Run Code Online (Sandbox Code Playgroud)

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

\*05.|__|##|.T|__|__|
Run Code Online (Sandbox Code Playgroud)

现在,由于|手段regexp,命令将其评估为:

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

  • _,或

  • #,或

  • 任何字符后跟T,或

  • _,或

  • _,或

  • 没有

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

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

当你比较它时*05 |__|##|__|__|__|,同样的事情发生:

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


修复

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

\*05.\|__\|##\|.T\|__\|__\|
Run Code Online (Sandbox Code Playgroud)

然后正则表达式将其读作:

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

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

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


大括号做什么?

大括号阻止在将表达式发送到regexp过程之前对其进行求值.因此,表达式将与您输入的表达式保持一致.如果你把:

{\\*05.\\|__\\|##\\|.T\\|__\\|__\\|}
Run Code Online (Sandbox Code Playgroud)

regexp将接收\\*05.\\|__\\|##\\|.T\\|__\\|__\\|和解释为\0次或更多次05,然后是任何字符,a \,OR等....

这就是为什么你不用双括号逃脱:

{\*05.\|__\|##\|.T\|__\|__\|}
Run Code Online (Sandbox Code Playgroud)

regexp将接收的表达式\*05.\|__\|##\|.T\|__\|__\|是在之前"\\*05.\\|__\\|##\\|.T\\|__\\|__\\|"处理之后的表达式.