我想使用grep
命令获取行号,但是当搜索模式不是单个词时,我收到错误消息:
couldn't read file "Pattern": no such file or directory
如何正确使用grep?代码在这里:
set status [catch {eval exec grep -n '$textToGrep' $fileName} lineNumber]
if { $status != 0 } {
#error
} else {
puts "lineNumber = $lineNumber"
}
此外,如果搜索模式完全不匹配,则返回的值为:"child process exited abnormally"
以下是简单的测试用例:
set textToGrep "<BBB name=\"BBBRM\""
文件内容:
<?xml version="1.0"?>
<!DOCTYPE AAA>
<AAA>
<BBB name="BBBRM" />
</AAA>
答案 0 :(得分:2)
好吧,我的代码和单个单词模式也出现了问题!
首先,我认为您不需要eval
命令,因为catch
本身会对其第一个参数进行评估。
然后,问题是您将$textToGrep
变量放在exec
内的单引号'
中,这对Tcl没有意义。
因此,如果textToGrep
的内容为foo
,则您要求grep
搜索字符串'foo'
。如果在文件中找不到包含单引号的字符串,则会收到错误。
尝试使用
重写第一行set status [catch {exec grep -n $textToGrep $fileName} lineNumber]
看看它是否有效。另外,请阅读exec
手册页,其中解释了这些问题。
答案 1 :(得分:2)
如果您的系统安装了tcllib,则可以使用fileutil::grep
包中的fileutil
命令:
package require fileutil
set fileName data.xml
set textToGrep {<BBB +name="BBBRM"}; # Update: Add + for multi-space match
set grepResult [::fileutil::grep $textToGrep $fileName]
foreach result $grepResult {
# Example result:
# data.xml:4: <BBB name="BBBRM" />
set lineNumber [lindex [split $result ":"] 1]
puts $lineNumber
# Update: Get the line, squeeze the spaces before name=
set line [lindex [split $result ":"] 2]
regsub { +name=} $line " name=" line
puts $line
}
textToGrep
分配值时,我使用了大括号,因此允许在内部使用双引号而不必转义它们。::fileutil::grep
命令的结果是一串字符串。每个字符串包含文件名,行号和行本身;用冒号分开。lindex
来获取第二个项目(index = 1,因为list是零基础的。)答案 2 :(得分:1)
set textToGrep {\<BBB name="BBBRM"}
catch {exec grep -n $textToGrep $fileName} status
if {![regexp "child process" $status]} {
puts $status
} else {
puts "no word found"
}
我认为你应该用子进程做正则表达式。如果有效,请检查上面的代码。在if语句中,您可以根据需要处理status命令。
使用给定的示例(在您的帖子中)上面的代码只有你需要使用反斜杠“&lt;”在textToGrep变量中
答案 3 :(得分:1)
这里有两个问题:
child process
exited abnormally
第一个问题是因为您没有将textToGrep
括在double quotes
内(而不是单引号)。所以你的代码应该是:
[catch {exec grep -n "$textToGrep" $fileName} lineNumber]
第二个问题是因为grep
命令的退出状态。未找到模式时,grep
会退出并出错。这是关于shell的尝试:
# cat file
pattern
pattern with multiple spaces
# grep pattern file
pattern
pattern with multiple spaces
# echo $?
0
# grep nopattern file
# echo $?
1
编辑:
在您的情况下,您有特殊字符,例如<
和>
(在shell上具有特殊含义)。
set textToGrep "<BBB name=\"BBBRM\""
regsub -all -- {<} "$textToGrep" "\\\<" textToGrep
regsub -all -- {>} "$textToGrep" "\\\>" textToGrep