【问题标题】:grep from file, print matched and unmatched从文件中grep,打印匹配和不匹配
【发布时间】:2012-11-23 14:41:51
【问题描述】:

我有一个文件,比如输入,包含如下模式:

quantum_mech_.*
astrophysics_.*
geology_.*
economy_*

我有另一个文件,比如主题,它看起来像:

quantum_mech_[101]
astrophysics_[102]
geology_[203]
quantum_mech_[007]
geology_[205]

我想 grep 输入文件中的每一行并搜索文件“主题”并仅输出第一个匹配项,如果在主题文件中根本找不到该行,则还打印“不匹配”。所以我期待这样的输出:

quantum_mech_[101]
astrophysics_[102]
geology_[203]
Not Matched

我知道这是一个很老的问题,但似乎没有一种方法对我来说正常工作。我尝试了以下代码的几种变体:

script.csh:

cat $1 | while read line
do grep $line ./subject | head -1 >> output
set VAR=$?
if ( $VAR==0 ) then 
        echo "Not Matched\n" >> output
endif
done

运行方式:

    script.csh input

任何使用 sed/grep/csh 的帮助/指针都会很棒。

感谢和问候,

【问题讨论】:

  • 你用的是什么外壳? csh?您的 while 循环的 csh 语法错误。
  • 是的,我正在使用 csh,我不是专家 :( 你能更正代码吗?谢谢
  • 不要使用 csh 编写脚本。谷歌“csh 为什么不”。

标签: unix sed grep pattern-matching csh


【解决方案1】:

这是使用awk的一种方式:

awk -F "[.*[]" 'FNR==NR && !($1 in a) { a[$1]=$2 } FNR!=NR { print ($1 in a) ? $1 "[" a[$1] : "Not Matched" }' subjects input

结果:

quantum_mech_[101]
astrophysics_[102]
geology_[203]
Not Matched

【讨论】:

  • 卡在我的外壳里太久了。 (文件很大)。但我通过 Viveks 回复解决了问题,非常感谢您的帮助
【解决方案2】:

这将打印除文本“不匹配”之外的每个不匹配的 RE,以便您知道哪些 RE 不匹配:

$ awk '
NR==FNR{ a[$0]; next }
{ for (re in a) if ($0 ~ re) { print; delete a[re] } }
END{ for (re in a) print re, "Not Matched" }
' file1 file2
quantum_mech_[101]
astrophysics_[102]
geology_[203]
economy_* Not Matched

它适用于 file1 中的任何 RE 和 file2 中的任何值。

【讨论】:

  • 感谢您的回复。但它并没有给出与我使用 Vivek 的代码相同的输出:(无论如何非常感谢
  • Awk 是您问题的正确解决方案。任何时候你发现自己在 shell 中编写了一个循环,你应该花一点时间重新考虑你在做什么,因为这通常是错误的方法。如果我发布的脚本没有产生您想要的输出,那么值得您花时间告诉我们输出有什么问题,这样我们就可以帮助您找出您的输入文件或您的 awk 版本有什么问题使用。
【解决方案3】:

这在 csh 和 bash 中运行良好。

for line in `cat $1`;
do
  grep -m1 $line ./subject || echo "Not matched"
done >> output

感谢 dogbane 的指针,下面是一个更好(和正确)的方法来做同样的事情。当行中有空格时,上述内容也存在问题。

while read line 
do
  grep -m1 "$line" ./subject || echo "Not matched"
done < $1 >> output

【讨论】:

  • 即使发布了更正,对于包含反斜杠或名称包含空格的文件也会失败。始终将您的 while 循环写为 while IFS= read -r line 并始终引用您的变量,即 "$1" 而不是 $1
最近更新 更多