打印出來的線現在我有這樣的代碼找到字符串之前和離職後UNIX腳本
FNR==NR { id[$0]; next }
$0 in id { f=1 }
f
NF==0 { f=0 }
,我想打印出前行字符串中找到爲好。
我該如何修改這段代碼呢?
打印出來的線現在我有這樣的代碼找到字符串之前和離職後UNIX腳本
FNR==NR { id[$0]; next }
$0 in id { f=1 }
f
NF==0 { f=0 }
,我想打印出前行字符串中找到爲好。
我該如何修改這段代碼呢?
這是我提到的Perl腳本sgrep
。今年的變化是使用#!/usr/bin/env perl
而不是#!/path/to/perl/v5.16.2/bin/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的grep,或支持-C
一個grep的,你可以這樣做:
grep -w -f file1 -C 1 input
的-w
使得grep
只匹配整個單詞,意在模仿你awk
腳本的 匹配,反而會不是完全相同的事情(我不清楚你到底想要做什麼匹配)你可能更喜歡忽略-w
。
在awk中,你可以這樣做:
FNR==NR { id[$0]; next }
$0 in id { print prev; f=1 }
f{ f += 1; print}
f == 3 { f=0 }
{ prev = $0 }
想必,你得是一個'awk'腳本。也許你有GNU'grep',在這種情況下,你可以使用'grep -B 1 -A 1 pattern file1 ...'來獲取每次比賽前後的線。在'awk'中,你必須保留前一行,這樣當你找到一個匹配時,你可以打印上一行。但是你必須擔心在兩條連續的線上,或者在一條線上和下一條線上尋找模式(所以你需要打印5行; line1,match1,line3,match2,line5)。 – 2013-03-15 02:28:02
我將如何保持前一行?有沒有一種方法可以將grep腳本和awk結合在一個腳本中? – 2013-03-15 03:20:36
如果你有GNU'grep',那麼也沒有必要使用'awk'。如果你沒有GNU'grep',那麼你需要考慮哪些行需要打印。我有一個處理這個工作的Perl腳本;它不是'awk',我不想'awk'重寫它,雖然它可能不是很難(事實上,選項處理可能會最困難,但這可以在shell腳本中完成)正確設置awk)。 – 2013-03-15 03:47:35