三个文件中的示例数据。
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
<<
我使用awk在起始分隔符( XXX )和结束分隔符(&lt;&lt; )之间输出文件的部分内容。这有效:
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
<<
如何修改此命令以仅输出匹配的文件名?
答案 0 :(得分: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]
答案 1 :(得分:1)
我确信有人会使用find
和exec
或xargs
提出一个聪明的解决方案,但只需使用bash
和{ {1}}。
awk
或拆分成更合理的shell脚本
> 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
<<
如果你想要它是递归的并且正在使用bash 4+,你可以用
替换起始for循环#!/bin/bash
for file in "/d/Temp/temp/"*.txt; do
res=$(awk '/XXX/,/<</' "$file")
[[ $res != "" ]] && echo "$file" && echo "$res"
done
如果您使用的是旧版本的bash,则可以将其替换为> shopt -s globstar; for file in /d/Temp/temp/**/*.txt; do
循环
find