2013-03-15 3 views
-1

방과후 라인을 인쇄하는 것은 지금이 코드문자열을 찾아 전에 유닉스 스크립트

FNR==NR { id[$0]; next } 
$0 in id { f=1 }   
f       
NF==0 { f=0 } 

을 가지고 내가 문자열뿐만 아니라 발견하기 전에 라인을 인쇄하고 싶습니다.

어떻게하면이 코드를 수정할 수 있습니까 ??

+1

, 당신이있어 것은'awk' 스크립트입니다

AWK, 당신은 뭔가를 할 수 있습니다. 어쩌면 당신은 GNU'grep'을 가지고있을 것입니다.이 경우'grep -B 1 -A 1 pattern file1 ... '을 사용하여 매치 전후에 줄을 얻을 수 있습니다. 'awk'에서 이전 줄을 지켜야 일치 항목을 찾을 때 이전 줄을 인쇄 할 수 있습니다. 그러나 두 개의 연속 된 줄 또는 한 줄과 그 다음 줄에 패턴을 찾는 것에 대해 걱정해야합니다 (그래서 line1, match1, line3, match2, line5의 5 줄을 인쇄해야합니다). –

+0

어떻게 이전 줄을 유지할 수 있을까요 ?? 하나의 스크립트에서 grep 스크립트와 awk를 결합 할 수있는 방법이 있습니까? –

+0

GNU'grep '을 가지고 있다면'awk'도 사용할 필요가 없습니다. GNU'grep '을 가지고 있지 않다면 어떤 줄이 인쇄가 필요한지 생각할 필요가 있습니다. 나는 그 일을 처리하는 Perl 스크립트를 가지고있다; 그것은 awk가 아니며 awk에서 다시 작성하지는 않을 것입니다. (아마도 옵션 처리가 실제로는 가장 힘들지는 않지만 쉘 스크립트에서 할 수 있습니다. awk를 올바르게 설정합니다). –

답변

2

다음은 내가 언급 한 Perl 스크립트입니다 (sgrep). 올해 변경된 내용은 #!/path/to/perl/v5.16.2/bin/perl 행 대신 #!/usr/bin/env perl을 사용하는 것이 었습니다. 그렇지 않으면 2007 년 9 월에 작성되었습니다. 개선의 여지가 있다고 생각합니다.

#!/usr/bin/env perl 
# 
# @(#)$Id: sgrep.pl,v 1.7 2013/01/28 02:07:18 jleffler Exp $ 
# 
# Perl-based SGREP (special grep) command 
# 
# Print lines around the line that matches (by default, 3 before and 3 after). 
# By default, include file names if more than one file to search. 
# 
# Options: 
# -b n1  Print n1 lines before match 
# -f n2  Print n2 lines following match 
# -n  Print line numbers 
# -h  Do not print file names 
# -H  Do  print file names 

use warnings; 
use strict; 
use constant debug => 0; 
use Getopt::Std; 
my(%opts); 

sub usage 
{ 
    print STDERR "Usage: $0 [-hnH] [-b n1] [-f n2] pattern [file ...]\n"; 
    exit 1; 
} 

usage unless getopts('hnf:b:H', \%opts); 
usage unless @ARGV >= 1; 

if ($opts{h} && $opts{H}) 
{ 
    print STDERR "$0: mutually exclusive options -h and -H specified\n"; 
    exit 1; 
} 

my $op = shift; 

print "# regex = $op\n" if debug; 

# print file names if -h omitted and more than one argument 
$opts{F} = (defined $opts{H} || (!defined $opts{h} and scalar @ARGV > 1)) ? 1 : 0; 
$opts{n} = 0 unless defined $opts{n}; 

my $before = (defined $opts{b}) ? $opts{b} + 0 : 3; 
my $after = (defined $opts{f}) ? $opts{f} + 0 : 3; 

print "# before = $before; after = $after\n" if debug; 

my @lines =(); # Accumulated lines 
my $tail = 0; # Line number of last line in list 
my $tbp_1 = 0; # First line to be printed 
my $tbp_2 = 0; # Last line to be printed 

# Print lines from @lines in the range $tbp_1 .. $tbp_2, 
# leaving $leave lines in the array for future use. 
sub print_leaving 
{ 
    my ($leave) = @_; 
    while (scalar(@lines) > $leave) 
    { 
     my $line = shift @lines; 
     my $curr = $tail - scalar(@lines); 
     if ($tbp_1 <= $curr && $curr <= $tbp_2) 
     { 
      print "$ARGV:" if $opts{F}; 
      print "$curr:" if $opts{n}; 
      print $line; 
     } 
    } 
} 

# General logic: 
# Accumulate each line at end of @lines. 
# ** If current line matches, record range that needs printing 
# ** When the line array contains enough lines, pop line off front and, 
# if it needs printing, print it. 
# At end of file, empty line array, printing requisite accumulated lines. 

while (<>) 
{ 
    # Add this line to the accumulated lines 
    push @lines, $_; 
    $tail = $.; 

    printf "# array: N = %d, last = $tail: %s", scalar(@lines), $_ if debug > 1; 

    if (m/$op/o) 
    { 
     # This line matches - set range to be printed 
     my $lo = $. - $before; 
     $tbp_1 = $lo if ($lo > $tbp_2); 
     $tbp_2 = $. + $after; 
     print "# $. MATCH: print range $tbp_1 .. $tbp_2\n" if debug; 
    } 

    # Print out any accumulated lines that need printing 
    # Leave $before lines in array. 
    print_leaving($before); 
} 
continue 
{ 
    if (eof) 
    { 
     # Print out any accumulated lines that need printing 
     print_leaving(0); 
     # Reset for next file 
     close ARGV; 
     $tbp_1 = 0; 
     $tbp_2 = 0; 
     $tail = 0; 
     @lines =(); 
    } 
} 

그것은 대신 -A-B의 경기 후 라인에 대한 옵션 경기 전에 라인 -b 1-f 1를 사용합니다. 당신은 GNU 그렙, 또는 -C를 지원하는 GREP이있는 경우

0

, 당신이 할 수 있습니다

grep -w -f file1 -C 1 input 

-wgrep는 전체 단어 만 일치하게하고 awk 스크립트의 매칭을 모방하기위한 것입니다,하지만 것입니다 꽤 똑같은 일을하지 마십시오 (당신이하고 싶은 것과 정확히 정확히 일치하지 않습니다) -w을 생략하는 것이 좋습니다. 아마도

FNR==NR { id[$0]; next } 
$0 in id { print prev; f=1 }   
f{ f += 1; print}       
f == 3 { f=0 } 
{ prev = $0 }