0

当我不将以下命令写入脚本文件时,它可以正常工作,但是当我将此命令放入脚本文件时,它会显示错误。

nawk 'c-- >0;$0~s{if(b)for(c=b+1;c >1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=10 a=10 s="string pattern" file

错误是:

nawk: syntax error at source line 1 context is >>> ' <<< missing }
nawk: bailing out at source line 1

对“你的脚本是什么样子”的众多请求之一的评论回复之一是:

#!/bin/ksh
Stringname=$1
directory=$2
d=$3
Command="nawk 'c-- >0;$0~s{if(b)for(c=b+1;c >1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=10 a=10 s=\"$stringname\" $directory"
$Command> $d

将整个命令存储在这样的字符串中非常令人担忧;不要这样做!这是不必要的,而且非常非常难以做到正确。

#!/bin/ksh
Stringname=$1
directory=$2
d=$3
nawk 'c-- >0;$0~s{if(b)for(c=b+1;c >1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=10 a=10 s="$stringname" $directory > $d
4

2 回答 2

1

我敢打赌你正在尝试执行你的脚本nawk -f file而不是仅仅./file.

于 2012-11-20T01:15:18.720 回答
1

解决匹配前打印 N 行和匹配后打印 M 行问题的最快方法是安装 GNUgrep并使用:

grep -B $N -A $M 'string pattern' file

如果做不到这一点,这是我大约 5 年前用来完成这项工作的 Perl 脚本。请注意,如果您要求比赛前 10 行和比赛后 10 行,则会出现一些复杂情况,并且您有:

  • 第 7 行的匹配项(之前不是 10 行)
  • 第 30 行匹配,第 35 行匹配(需要打印第 20-45 行)
  • 第 60 行的匹配,其中最后一行是第 65 行(之后不是 10 行)
  • 并且有多个文件要处理。

这段代码确实处理了所有这些。它可能可以改进。

#!/usr/bin/perl -w
#
# @(#)$Id: sgrep.pl,v 1.6 2007/09/18 22:55:20 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 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 = ();
    }
}
于 2012-11-19T20:00:10.730 回答