捕获有关文件和找到的正则表达式的信息

时间:2013-04-14 21:32:12

标签: regex bash grep

我的目录中包含了我想要捕获的数字的文件。我还想知道哪些数字来自哪些特定文件。现在我只是运行grep,输出类似:

grep ./* -e 'expression'
./file1: expression numberA
./file1: expression numberB
./file1: expression numberA
./file2: expression numberC numberD
...

我想要的是提取一段文件名(在本例中,1代表file1),以及我表达后出现的所有数字。

虽然我更喜欢用bash做所有事情,但欢迎任何解决方案。

编辑:要清楚,我想要输出以下内容:

file1:
numberA
numberB
file2:
numberC
numberD
...

我还编辑了前面的部分(./file1:表达式编号A)。很抱歉以前不清楚。

4 个答案:

答案 0 :(得分:1)

试试这个:

grep -e 'expression' * | perl -pe 's/^(.*?)(\d+)(:.*)$/$1$2$3 $2/'

这应该产生所有输入行。如果输入行的文件名部分以数字结尾,则该数字应附加到输入行。

$1$2$3是3个子表达式的反向引用(括号中正则表达式的那些部分)。

命令行开关-e指示Perl解释器执行给定的表达式。 -p在输入上循环并打印$_

但是,由于你也想要在比赛结束后获得所有数字,你可能需要更复杂的东西:

grep -e 'expression' * | perl -ne '
  chomp;
  ($a,$b) = split ":";
  $a =~ s/.*(\d+)$/$1/;
  $b =~ s/.*expression(.*)/$1/;
  $b =~ s/[^\d]+/ /g;
  print "$_ $a $b\n";
'

-n-p的效果相同,但不会隐式打印$_

编辑:在阅读完更新的要求后,我认为使用全Perl解决方案可能会更好。

#!/usr/bin/env perl

use strict;
use warnings;

foreach (@ARGV) {
  my $file = $_;
  open FILE, "<$file" or die "Can't open file $file.";
  my $first = 1;
  foreach (<FILE>) {
    if (m/expression(.*)/) {
      my $values = $1;
      if ($first) {
        print "$file:\n";
        $first = 0;
      }
      $values =~ s/(^ +| +$)//g;
      $values =~ s/ +/\n/g;
      print "$values\n";
    }
  }
  close FILE;
}

答案 1 :(得分:0)

如果您只想查看文件编号和数字,可以使用以下内容:

find . -exec sh -c "echo -n \;{}::;grep -e 'expression' {}" \; | perl -pe 's/^.*(\d+)::/File \1:\n/' | perl -pe 's/\D*(\d+)$/\1/'

注意:如果您的表达式包含::number(用作分隔符,可以更改),这将会中断。如果未找到匹配项,则打印上一个文件名。

会产生:

File 2:
878
File 3:
199
File 4:
123
234
9
0

示例文件2:

foo 123
bar 123
expression 878
lorem ipsum

如果您只想要数字对(文件编号+数字),那么您可以尝试:

grep ./* -e 'expression' | perl -pe 's/^.*?(\d+):.*?(\d+)$/\1 \2/'

输出:

2 878
3 199
4 123
4 234
4 9
4 0

正如我的评论中提到的,你的问题在你想要的确切内容上有点不清楚。提供一些例子将是有益的。

答案 2 :(得分:0)

感谢两位回答的人 - 根据你们双方给我的信息,我能够找到一个完美的解决方案:

grep -i expression ./* | perl -pe 's/.*(\d+).*:.*(\d+)/$1 $2/' | sort | uniq

这给出了输出:

1 numberA
1 numberB
2 numberC numberD

答案 3 :(得分:0)

我认为在这种情况下不需要grep。需要awk或perl来累积数据,因此他们可以在文件中查找表达式。这是一个例子:

awk '/expression/ {f[FILENAME]; for(i=2;i<=NF;++i) v[FILENAME,$i]} 
END {for(i in f) {print i":"; for(j in v) if(sub("^"i SUBSEP,"",j))print j}}' ./*

输出

file1:
numberB
numberA
file2:
numberD
numberC