我有一个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第一个实例并将其写入文件的正确方法吗?
答案 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
作为奖励,我还重定向了一个块,而不是单独指定每个命令(也许你现在可以使用>
?)并安全地引用你的变量。