我正在使用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
%
我不知道为什么它会以这种方式行事,如果有人能告诉我这里出了什么问题以及如何纠正它,那将会非常棒。
答案 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