【问题标题】:grep command giving unexpected output when searching exact word in file in cshgrep 命令在 csh 中搜索文件中的确切单词时给出意外输出
【发布时间】:2023-07-30 15:46:01
【问题描述】:

我使用以下脚本在另一个文件中搜索一个文件的每一行,如果找到打印该行的第二列:

#!/bin/csh

set goldFile=$1
set regFile=$2

set noglob
foreach line ("`cat $goldFile`")
    set searchString=`echo $line | awk '{print $1}'`
    set id=`grep -w -F "$searchString" $regFile | awk '{print $2}'`
    echo "$searchString" "and" "$id"
end

unset noglob

黄金文件如下:

\$#%$%escaped.Integer%^^&[10]
\$#%$%escaped.Integer%^^&[10][0][0][31]
\$#%$%escaped.Integer%^^&[10][0][0][30]
\$#%$%escaped.Integer%^^&[10][0][0][29]
\$#%$%escaped.Integer%^^&[10][0][0][28]
\$#%$%escaped.Integer%^^&[10][0][0][27]
\$#%$%escaped.Integer%^^&[10][0][0][26]

RegFile 如下:

\$#%$%escaped.Integer%^^&[10] 1
\$#%$%escaped.Integer%^^&[10][0][0][31] 10
\$#%$%escaped.Integer%^^&[10][0][0][30] 11
\$#%$%escaped.Integer%^^&[10][0][0][29] 12
\$#%$%escaped.Integer%^^&[10][0][0][28] 13
\$#%$%escaped.Integer%^^&[10][0][0][27] 14
\$#%$%escaped.Integer%^^&[10][0][0][26] 15

输出来了:

\$#%$%escaped.Integer%^^&[10] and 1 10 11 12 13 14 15
\$#%$%escaped.Integer%^^&[10][0][0][31] and 10
\$#%$%escaped.Integer%^^&[10][0][0][30] and 11
\$#%$%escaped.Integer%^^&[10][0][0][29] and 12
\$#%$%escaped.Integer%^^&[10][0][0][28] and 13
\$#%$%escaped.Integer%^^&[10][0][0][27] and 14
\$#%$%escaped.Integer%^^&[10][0][0][26] and 15

但预期的输出是:

\$#%$%escaped.Integer%^^&[10] and 1
\$#%$%escaped.Integer%^^&[10][0][0][31] and 10
\$#%$%escaped.Integer%^^&[10][0][0][30] and 11
\$#%$%escaped.Integer%^^&[10][0][0][29] and 12
\$#%$%escaped.Integer%^^&[10][0][0][28] and 13
\$#%$%escaped.Integer%^^&[10][0][0][27] and 14
\$#%$%escaped.Integer%^^&[10][0][0][26] and 15

请帮我弄清楚如何使用 grep 搜索具有某些特殊字符的确切单词。

【问题讨论】:

  • bashcsh 是两个不同的shell,不要指望它是相互关联的,去掉这里不相关的标签。
  • @Inian 我刚刚分享了失败案例。这两个文件都包含很多值。
  • 失败是因为-F固定字符串标志,gold文件中的\$#%$%escaped.Integer%^^&[10]行匹配reg文件中的所有输入行。
  • 您不能使用^$ 为其添加单词边界,代价是它会成为字符串的一部分。
  • reg文件中的gold文件中的每一行是否只有一个匹配,如果是这种情况,可以修复

标签: bash shell grep csh


【解决方案1】:

cshbash 是完全不同的 shell 变体。他们甚至不应该兼容。您的问题与grep的使用有关

由于grep 中的-F 标志可以让您的字符串成为固定模式,容易包含各种正则表达式特殊字符,例如,,[],(),.,@ 987654330@,^,$,-,\

错误结果是因为-F标志,Gold文件中的\$#%$%escaped.Integer%^^&[10]行匹配RegFile上的所有输入行。

所以通常搜索的确切单词可以通过单词边界构造 ^$ 作为模式的一部分进行过滤,但由于 -F, --fixed-strings 标志它们将在您的情况下不起作用被视为搜索字符串的一部分。

因此假设从输入文件中,Gold 文件中的每一行与RegFile 可能只有一个一个匹配项,您可以在第一次命中后停止grep 搜索 p>

使用-m1 标志,根据man grep 页面所述,

-m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.  If the input is standard input 
          from a regular file, and NUM matching lines are output, grep ensures that the 
          standard input  is  positioned  to just  after  the  last  matching  line  before  
          exiting,  regardless of the presence of trailing context lines.  

所以添加它就像,

grep -w -F -m1 "$searchString" $regFile

应该可以解决你的问题。

【讨论】: