2014-01-22 50 views
1

三個文件中的示例數據。使用awk/find輸出結果和文件名

fileOne.txt

YYY >> 
yyy one 
yyy two 
yyy three 
<< 

ZZZ >> 
zzz one 
zzz two 
zzz three 
<< 

fileTwo.txt

XXX >> 
xxx one 
xxx two 
xxx three 
<< 

fileThree.txt

XXX >> 
xxx one 
xxx two 
xxx three 
<< 

ZZZ >> 
zzz one 
zzz two 
zzz three 
<< 

我使用AW k輸出起始分隔符(XXX)和結束分隔符(< < <)之間的文件部分。這工作:

awk '/XXX/,/<</' /d/Temp/temp/*.txt 

結果

XXX >> 
xxx one 
xxx two 
xxx three 
<< 
XXX >> 
xxx one 
xxx two 
xxx three 
<< 

但是我要輸出的文件名了。查找類似的作品,但它結束了印刷全部的文件名。

find /d/Temp/temp/ -type f -name "*.txt" -print -exec awk '/XXX/,/<</' {} \; 

結果

/d/Temp/temp/fileOne.txt 
/d/Temp/temp/fileThree.txt 
XXX >> 
xxx one 
xxx two 
xxx three 
<< 
/d/Temp/temp/fileTwo.txt 
XXX >> 
xxx one 
xxx two 
xxx three 
<< 

我怎麼能修改此命令只輸出匹配的文件名?

回答

2

用awk

awk '/XXX/,/<</{print a[FILENAME]?$0:FILENAME RS $0;a[FILENAME]++}' *.txt 

說明:

/XXX/,/<</      # output portions of the file between start delimiter (XXX) and end delimiter (<<). 
a[FILENAME]?     # assign filename as key to array `a`, determine whether it is the true (>0) or fails (0 or null) 
a[FILENAME]?$0:FILENAME RS $0 # if true, print the line only, if fail, print filename and the current line 
a[FILENAME]++     # increase the value of array a[FILENAME] 
+0

+1一如繼往的爲短一行'awk'(也可以通過只是在做遞歸做'**/* txt'與globstar)。你能簡單地解釋一下你在答案中使用的邏輯嗎? – BroSlow

+0

我已經添加了解釋。 – BMW

+0

我想在腳本中使用它,所以我還需要在awk命令部分中轉義$,以便可以使用位置參數:'awk「/ $ {1} /,/ <

1

我敢肯定有人會拿出來與findexecxargs一個聰明的解決方案,但可以只使用bashawk可以很簡單地完成。

> for file in /d/Temp/temp/*.txt; do res=$(awk '/XXX/,/<</' "$file"); [[ $res != "" ]] && echo "$file" && echo "$res"; done 
/d/Temp/temp/fileThree.txt 
XXX >> 
xxx one 
xxx two 
xxx three 
<< 
/d/Temp/temp/fileTwo.txt 
XXX >> 
xxx one 
xxx two 
xxx three 
<< 

或分割成更合理的期待shell腳本

#!/bin/bash 
for file in "/d/Temp/temp/"*.txt; do 
    res=$(awk '/XXX/,/<</' "$file") 
    [[ $res != "" ]] && echo "$file" && echo "$res" 
done 

如果你希望它是遞歸和使用bash 4+,你可以用

> shopt -s globstar; for file in /d/Temp/temp/**/*.txt; do 
替換for循環的開始

如果您使用的是較舊版本的bash,您可以用find循環代替它

> find /d/Temp/temp/ -type f -name "*.txt" -print0 | while read -r -d '' file; do