使用GREP搜索文件的特定行

问题描述

我有一个包含许多文本文件的目录。我想在文件的特定行中搜索给定的字符串(例如在每个文件的第二行和第三行中搜索“ abc”)。然后,当我找到一个匹配项时,我要打印匹配文件的第1行。

我的方法-我正在使用-n选项进行grep搜索,并将输出存储在另一个文件中,然后在该文件搜索行号。然后,我尝试获取文件名,然后打印出第一行。

使用我上面提到的方法,即使我知道此方法非常冗长,也无法获取正确文件文件名。

是否有更好,更快速解决方案?

例如
1.txt

file 1
one
two

2.txt

file 2
two
three

我想使用grep在每个文件的第二行中搜索“两个”,然后打印匹配的文件的第一行。在此示例中,该文件应为2.txt,输出应为“文件2”

我知道使用sed / awk会更容易,但是有没有办法使用grep 来做到这一点?

解决方法

改为使用sed(GNU sed):

parse.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
  }
}

像这样运行它:

sed -snf parse.sed file1 file2 ...

或者作为单线:

sed -sn '1h; 2,3 { /my pattern/ { x; p; :a; n; ba; } }' file1 file2 ...

您可能还希望发出文件名,例如带有示例数据:

parse2.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
  }
}

像这样运行它:

sed -snf parse2.sed file1 file2 | paste -d: - -

输出:

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将具有正在读取的当前文件的行号
    • 如果需要行数,请使用FNR>=2 && FNR<=3
  • FNR==1{line=$0}将保存第一行的内容以供将来使用
  • nextfile应该受大多数实现的支持,但是如果您需要删除该解决方案,它仍然可以运行(速度较慢)
,

使用grepbash

# 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

输出:

file 1
,

仅使用grepcut|(管道):

grep -rnw pattern dir | grep ":line_num:" | cut -d':' -f 1

说明

grep -rnw pattern dir

它返回找到模式的文件的名称以及行号。 它的输出将是这样的

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

现在我使用另一个grep来获取具有正确行号的文件(例如,包含第2行中的模式的文件)

grep -rnw pattern dir | grep ":2:"

输出为

path/to/file/file3(.txt):2:line

现在我正在使用cut来获取文件名

grep -rnw pattern dir | grep ":2:" | cut -d':' -f 1

它将输出这样的文件名

path/to/file/file3(.txt)

P.S。 -如果要从文件名中删除“ path / to / file /”,则可以依次使用revcutrev,也可以自己尝试或查看下面的代码

grep -rnw pattern dir | grep ":2:" | cut -d':' -f 1 | rev | cut -d'/' -f 1 | rev

感谢您的阅读!