[英]Searching specific lines of files using GREP
I have a directory with many text files.我有一个包含许多文本文件的目录。 I want to search a given string in specific lines in the files(like searching for 'abc' in only 2nd and 3rd line of each file).我想在文件的特定行中搜索给定的字符串(例如仅在每个文件的第 2 行和第 3 行中搜索“abc”)。 Then When I find A match I want to print line 1 of the matching file.然后,当我找到匹配项时,我想打印匹配文件的第 1 行。
My Approach - I'm doing a grep search with -n option and storing the output in a different file and then searching that file for the line number.我的方法 - 我正在使用 -n 选项进行 grep 搜索并将 output 存储在不同的文件中,然后在该文件中搜索行号。 Then I'm trying to get the file name and then print out it's first line.然后我试图获取文件名,然后打印出它的第一行。
Using the approach I mentioned above I'm not able to get the file name of the right file and even if I get that this approach is very lengthy.使用我上面提到的方法我无法获得正确文件的文件名,即使我知道这种方法非常冗长。
Is there a better and fast solution to this?对此有更好更快的解决方案吗?
Eg.例如。
1.txt 1.txt
file 1
one
two
2.txt 2.txt
file 2
two
three
I want to search for "two" in line 2 of each file using grep
and then print the first line of the file with match.我想使用grep
在每个文件的第 2 行中搜索“two”,然后使用匹配打印文件的第一行。 In this example that would be 2.txt and the output should be "file 2"在这个例子中是 2.txt 而 output 应该是“文件 2”
I know it is easier using sed
/ awk
but is there any way to do this using grep
?我知道使用sed
/ awk
更容易,但是有没有办法使用grep
来做到这一点?
Use sed
instead (GNU sed):使用sed
代替(GNU sed):
parse.sed解析.sed
1h # Save the first line to hold space
2,3 { # On lines 2 and 3
/my pattern/ { # Match `my pattern`
x # If there is a match bring back the first line
p # and print it
:a; n; ba # Loop to the end of the file
}
}
Run it like this:像这样运行它:
sed -snf parse.sed file1 file2 ...
Or as a one-liner:或者作为单线:
sed -sn '1h; 2,3 { /my pattern/ { x; p; :a; n; ba; } }' file1 file2 ...
You might want to emit the filename as well, eg with your example data:您可能还想发出文件名,例如您的示例数据:
parse2.sed解析2.sed
1h # Save the first line to hold space
2,3 { # On lines 2 and 3
/two/ { # Match `my pattern`
F # Output the filename of the file currently being processed
x # If there is a match bring back the first line
p # and print it
:a; n; ba # Loop to the end of the file
}
}
Run it like this:像这样运行它:
sed -snf parse2.sed file1 file2 | paste -d: - -
Output: Output:
file1:file 1
file2:file 2
$ awk 'FNR==2{if(/one/) print line; nextfile} FNR==1{line=$0}' 1.txt 2.txt
file 1
$ awk 'FNR==2{if(/two/) print line; nextfile} FNR==1{line=$0}' 1.txt 2.txt
file 2
FNR
will have line number for the current file being read FNR
将具有当前正在读取的文件的行号
FNR>=2 && FNR<=3
if you need a range of lines如果需要一系列行,请使用FNR>=2 && FNR<=3
FNR==1{line=$0}
will save the contents of first line for future use FNR==1{line=$0}
会保存第一行的内容以备后用nextfile
should be supported by most implementations, but the solution will still work (slower though) if you need to remove it大多数实现都应该支持nextfile
,但如果您需要删除它,该解决方案仍然有效(虽然速度较慢)With grep
and bash
:使用grep
和bash
:
# Grep for a pattern and print filename and line number
grep -Hn one file[12] |
# Loop over matches where f=filename, n=match-line-number and s=matched-line
while IFS=: read f n s; do
# If match was on line 2 or line 3
# print the first line of the file
(( n == 2 || n == 3 )) && head -n1 $f
done
Output: Output:
file 1
Only using grep
, cut
and |
仅使用grep
, cut
和|
(pipe): (管道):
grep -rnw pattern dir | grep ":line_num:" | cut -d':' -f 1
Explanation解释
grep -rnw pattern dir
It return name of the file(s) where the pattern was found along with the line number.它返回找到模式的文件的名称以及行号。 It's output will be somthing like this它是 output 会是这样的
path/to/file/file1(.txt):8:some pattern 1
path/to/file/file2(.txt):4:some pattern 2
path/to/file/file3(.txt):2:some pattern 3
Now I'm using another grep
to get the file with the right line number (for eg file that contains the pattern in line 2)现在我正在使用另一个grep
来获取具有正确行号的文件(例如包含第 2 行模式的文件)
grep -rnw pattern dir | grep ":2:"
It's output will be它的 output 将是
path/to/file/file3(.txt):2:line
Now I'm using cut to get the filename现在我正在使用 cut 来获取文件名
grep -rnw pattern dir | grep ":2:" | cut -d':' -f 1
It will output the file name like this它将 output 这样的文件名
path/to/file/file3(.txt)
PS - If you want to remove the "path/to/file/" from the filename you can use rev
then cut
and again rev
, you can try this yourself or see the code below. PS - 如果您想从文件名中删除“path/to/file/”,您可以使用rev
然后cut
并再次rev
,您可以自己尝试或查看下面的代码。
grep -rnw pattern dir | grep ":2:" | cut -d':' -f 1 | rev | cut -d'/' -f 1 | rev
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.