将一个命令的输出作为参数传递给另一个命令

时间:2010-10-26 11:26:52

标签: unix shell awk grep design-patterns

我有 for

for i in `ls -1 access.log*`; do tail $i |awk {'print $4'} |cut -d: -f 1 |grep - $i > $i.output; done

ls 会提供access.log,access.log.1,access.log.2等 tail 会给我每个文件的最后一行,如下所示:192.168.1.23 - - [08/Oct/2010:14:05:04 +0300]等等。
awk + ​​cut 将提取日期(2010年10月8日 - 但在每个access.log中有所不同),这将允许我 grep 并将输出重定向到一个单独的文件。

但我似乎无法将awk + ​​cut的输出传递给grep。

所有这一切的原因是这些访问日志包括具有多个日期的行(06 / Oct,07 / Oct,08 / Oct),我只需要具有最新日期的行。

我怎样才能做到这一点?

谢谢。

5 个答案:

答案 0 :(得分:1)

为什么不把它分解成步骤?

for file in *access.log
do
  what=$(tail "$i" |awk {'print $4'} |cut -d: -f 1)
  grep "$what" "$file" >> output
done

答案 1 :(得分:1)

作为旁注,tail显示最后10行。

可能的解决方案是grep这样:

for i in `ls -lf access.log*`; do grep $(tail $i |awk {'print $4'} |cut -d: -f 1| sed 's/\[/\\[/') $i > $i.output; done

答案 2 :(得分:1)

您不应该以这种方式使用ls。此外,ls -l为您提供了您不需要的信息。 -f的{​​{1}}选项允许您将模式传递给grep。始终引用包含文件名的变量。

grep

我也取消了for i in access.log*; do awk 'END {sub(":.*","",$4); print substr($4,2)}' "$i" | grep -f - $i > "$i.output"; done tail因为AWK可以完成他们的工作。

答案 3 :(得分:0)

嗯... 使用xargs或反引号。

man xargs

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html,第3.4.5节。命令替换

答案 4 :(得分:0)

你可以尝试:

 grep "$(stuff to get piped over to be grep-ed)" file

我没试过这个,但我在这里应用的答案看起来像这样:

 grep "$(for i in `ls -1 access.log*`; do tail $i |awk {'print $4'} |cut -d: -f 1 |grep - $i > $i.output; done)" $i