使用grep获取行号

时间:2013-08-12 09:43:15

标签: tcl

我想使用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>

4 个答案:

答案 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是零基础的。)
  • 我已更新代码,以便在 name =
  • 之前有多个空格的情况下进行说明

答案 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)

这里有两个问题:

  • 模式匹配不起作用。
  • 当找不到模式时,grep退出并显示错误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