与grep进行第一场比赛

时间:2015-06-11 10:09:10

标签: bash grep

我有一个bash函数,它遍历某个单词的文件和greps列表并将其写入文件。问题是我得到了单词的每个实例,我只想得到第一个实例。我通过在grep中添加head -1来找到解决方案,但现在,当我调用它时,我的函数就会挂起。

 83 function processAppLogs {
 84         for i in `find $log_des -name $fname`
 85             do
 86                 p=$i
 87                 d=${p//applog.txt/unmountTimestampList.txt}
 88                 grep "UNMOUNTED"  $i >> $d
 89                 grep "PATIENT ID" | head -1 | $i >> $d
 90             done
 91 }

我希望只打算第一个" PATIENT ID"但我想我可能有错误的语法?这是grep第一个实例并将其写入文件的正确方法吗?

3 个答案:

答案 0 :(得分:7)

您可以使用-m 1表示您只想匹配一次:

grep -m 1 "PATIENT ID" >> "$d"

来自man grep

  

-m NUM , - max-count = NUM​​

     

NUM匹配行后停止读取文件。

测试

$ seq 8 12
8
9
10
11
12
$ seq 8 12 | grep 1 -m 1
10
$ seq 8 12 | grep 1 -m 2
10
11

答案 1 :(得分:1)

作为一方不要@ fedorqui的答案。

你错了的是命令的顺序。 head必须在grep之后发生,然后才能进行重定向。像

grep "PATIENT ID" $i | head -1  >> $d

答案 2 :(得分:1)

答案是使用-m来指定最大匹配数,如果您的grep版本支持它。否则,将输出汇总到head将起作用。 head将在达到指定的行数后退出,打破管道并导致grep退出,因此结果将是相同的(尽管以管道为代价)。

使用单个进程的便携式替代方法是使用awk:

awk '/PATIENT ID/ {print; exit}' "$i"

应避免使用for i in `find $log_des -name $fname` 之类的循环,因为它们依赖于行为良好的文件名(不存在空格或整数字符),否则会中断。

如果你依靠find来进行递归目录搜索,那么请改用globstar,因为它可以让你安全地做你想做的事。

shopt -s globstar
for i in **/"$fname"; do
    d=${i//applog.txt/unmountTimestampList.txt}
    { grep "UNMOUNTED" "$i"; grep -m 1 "PATIENT ID" "$i" } >> "$d"
done

作为奖励,我还重定向了一个块,而不是单独指定每个命令(也许你现在可以使用>?)并安全地引用你的变量。