I need to search for files which has string开发者_高级运维 str1 appearing before string str2. both strings are in separate lines.
for example, file1 looks like:
abc
def
str1
ghi
str2
file2 looks like:
abc
str2
def
ghi
str1
pqe
My search should return file1.
It should be a one liner script I can run on command line on unix.
Thanks in advance.
So, here is your awk
one liner
awk -vRS="\0777" '/str1.*str2/{print FILENAME}' file*
Sed 1 liner for above:
F="file1" && test ! -z $(sed -n '/str1/,/str2/{/^str2$/p;}' "$F") && echo "$F"
F="file2" && test ! -z $(sed -n '/str1/,/str2/{/^str2$/p;}' "$F") && echo "$F"
OUTPUT
file1
And here is awk one liner
F="file1" && awk '{if ($0 == "str1") {a=NR} else if ($0 == "str2" && a> 0 && a<NR) {print FILENAME} }' $F
F="file2" && awk '{if ($0 == "str1") {a=NR} else if ($0 == "str2" && a> 0 && a<NR) {print FILENAME} }' $F
OUTPUT
file1
This is not exactly an one-liner but you can delete the newlines and the problem is solved :)
for file in $(ls) ; do
awk "/str1/{found=1}/str2/{if(found) print \"$file\"}" $file
done
What does it do: for each file listed by ls
, if str1
appears in it, the script marks it in a variable found
:
/str1/{found=1}
then, when str2
appears in a line, it verifies if found
is set. If so, prints the file name:
/str2/{
if (found)
print "$file"
}
EDIT: there is still a more concise way to solve your problem, using find
and xargs
:
find . -print0 -maxdepth 1 | \
xargs -0 -I{} awk '/str1/{found=1}/str2/{if(found) print "{}"}' "{}"
It is safer, too, because it handles files with spaces in their names. Also, you can extend it to search in subdirectories just removing the -maxdepth 1
option. Note that the awk
script was not changed.
(There always is a good solution using find
and xargs
but this solution is always a bit hard to find :D )
HTH!
精彩评论