2010-10-26 166 views
2

我已经这个传递输出从一个命令作为参数传递给另一个

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等
会给我的每个文件的最后一行,它看起来像:192.168.1.23 - - [08/Oct/2010:14:05:04 +0300]等等,等等等等
AWK +切将提取的日期(08月/ 10月/ 2010 - 每个access.log的,但不同的),这将允许我grep,并将输出重定向到单独的文件。

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

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

我该如何做到这一点?

谢谢。

+0

你可以张贴一些示例输入和预期的输出? – 2010-10-26 11:29:59

+1

一个问题是,您为每个access.log保留覆盖相同的输出。请注意,您也可以使用多个尾部文件。 – Tomas 2010-10-26 11:31:44

+0

大声笑..你是对的,不知道我是如何忽略这个事实的。让我想一想,所以我可以想出一个解决方法。 – w00t 2010-10-26 11:35:48

回答

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 
+0

我不太在乎这方面。我可以使用tail -n 1. – w00t 2010-10-26 12:22:54

+0

@mouviciel - 我已经完全按照你写的那样尝试过了,但是它给了grep:无与伦比的[或[^ – w00t 2010-10-26 12:44:49

+0

我看,'['对'grep'有特殊含义。我编辑我的答案。 – mouviciel 2010-10-26 12:51:27

0

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

man xargs 

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

+0

我看不出xargs如何帮助我。它需要知道所有先前命令的输出是什么,然后将其作为模式传递给grep。它不会是'command | xargs grep 123 file.txt',但它会是'command | xargs grep -pattern-from-command-file.txt' – w00t 2010-10-26 12:40:35

1

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

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

这也会在每次迭代中覆盖'output'。 – 2010-10-26 11:37:31

+0

我想我可以分解它,但想从CLI运行它。总之,我不止一次需要使用这样的功能,所以我试图为我的场景找到答案。 – w00t 2010-10-26 11:55:16

+0

优雅的解决方案是重定向'done'来覆盖文件;这样,整个循环体被重定向,并且该文件被打开以便只写一次,在循环内重复进行。 – tripleee 2016-09-21 14:29:52

1

你不应该使用ls的方式。另外,ls -l为您提供您不需要的信息。将-f选项设置为grep将允许您将模式传送到grep。始终引用包含文件名的变量。

for i in access.log*; do awk 'END {sub(":.*","",$4); print substr($4,2)}' "$i" | grep -f - $i > "$i.output"; done 

我也消除了tailcut因为AWK可以做他们的工作。

+0

我认为ls -l没有问题,这是我习惯使用它的方式。我可以使用ls -1,但它并不重要。由于AWK读取整个文件以达到END,并且当文件大小为500 + mb时,AWK不是剪切和剪切作业的理想选择。现在关于grep -f,这真的很有帮助。谢谢。 – w00t 2010-11-02 08:19:20

+1

http://mywiki.wooledge.org/ParsingLs解释了为什么'ls'有问题。 – tripleee 2016-09-20 05:27:10

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 
相关问题