与变量名一起使用时,tcl regex无法正常工作

时间:2018-06-07 07:54:19

标签: regex grep tcl

我正在使用tcl来执行一些模式匹配。以下是我正在执行匹配的字符串:

ps -ef | grep ipqosmgr
root     17255 17136  0 22:34 ttyS0    00:00:00 grep ipqosmgr
root     28986 17731  0 Jun05 ?        00:02:01 /isan/bin/ipqosmgr

通常我会想要第3行

root     28986 17731  0 Jun05 ?        00:02:01 /isan/bin/ipqosmgr

因为我想要与流程相关联的流程ID。

当我使用以下正则表达式时,它按预期工作:

% foreach line [split $output \n] {
    if { [ regexp -nocase {root\s+([0-9]+)\s+.*(/isan/bin/ipqosmgr)} $line - value ] } {
        puts $line
    }
}
root     28986 17731  0 Jun05 ?        00:02:01 /isan/bin/ipqosmgr
% puts $value
28986
% 

但是,我希望这个代码能够运行多个进程,因此将它放在一个带有 $ process 的函数中,该函数将保存进程的值。当我使用与变量 $ process 相同的正则表达式时,它会失败。

% puts $process
ipqosmgr
%
% foreach line [split $output \n] {
    if { [ regexp -nocase {root\s+([0-9]+)\s+.*(/isan/bin/$process)} $line - value ] } {
        puts $line
    }
}
% 
% puts $value
can't read "value": no such variable
% 

我不知道为什么它会以这种方式行事,如果有人能告诉我这里出了什么问题以及如何纠正它,那将会非常棒。

3 个答案:

答案 0 :(得分:2)

您可以使用format准备正则表达式,如下所示:

     body { 
  background:  url("https://material.angular.io/assets/img/examples/shiba1.jpg");
    -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: 100% 100%;
  background-repeat: no-repeat;
 }

html{
  height: 100vh;
}

你使用表达式的方式的问题是大括号阻止变量替换,虽然你可以使用引号代替正则表达式,但你必须转义很多字符(例如方形的parens,反斜杠)和为了避免逃避这些,使用foreach line [split $output \n] { set regex [format {root\s+([0-9]+)\s+.*(/isan/bin/%s)} $process] if { [ regexp -nocase $regex $line - value ] } { puts $line } } 可以更简单地使用。

答案 1 :(得分:1)

如果您打算使用字符串iterpolation,则应该使用双引号字符串文字,并介意转义[]以防止将它们解释为命令以及转义每个\以定义文字反斜杠(例如,在这里使用速记字符类\s):

regexp -nocase "root\\s+(\[0-9\]+)\\s+.*(/isan/bin/$process)" $line - value

请参阅Tcl demo online

下面,

  • root - 子字符串root
  • \\s+ - 解析为\s+ - 一个或多个空白字符
  • (\[0-9\]+) - 解析为([0-9]+) - 捕获第1组 - 1位或更多位数
  • \\s+ - 一个或多个空格
  • .* - 任何0+字符
  • (/isan/bin/$process) - 解析为(/isan/bin/ipqosmgr) - 捕获与/isan/bin/ipqosmgr子字符串匹配的第1组(或任何/isan/bin/ + $process)。

答案 2 :(得分:1)

使用subst command的变量替换。此外,如果指定了-nobackslashes-nocommands-novariables中的任何一个,则不会执行相应的替换。例如,如果指定了-nocommands,则不执行命令替换:打开和关闭括号被视为普通字符,没有特殊解释。

% set output "
root     17255 17136  0 22:34 ttyS0    00:00:00 grep ipqosmgr
root     28986 17731  0 Jun05 ?        00:02:01 /isan/bin/ipqosmgr
"

并使用变量集

% set process "ipqosmgr"

你可以做得很好,

% foreach line [split $output \n] {
    if { [ regexp -nocase [subst -nocommands -nobackslashes {root\s+([0-9]+)\s+.*(/isan/bin/$process)}] $line - value ] } {
        puts $line
    }
}
root     28986 17731  0 Jun05 ?        00:02:01 /isan/bin/ipqosmgr

按预期进行匹配

% puts $value
28986