2

我遇到了一个很好的单行来搜索文本并打印出具有给定数量的尾随行和后续行的结果。我正在尝试从中创建一个脚本。到目前为止,这就是我所拥有的:

# *********************************************************
# This uses nawk to list lines coming prior to and after
# the given search string.
# Format: xgrep <string> <file> <before> <after>
# ********************************************************

STR=$1
FILE=$2
BEF=$3
AFT=$4
export STR
export FILE
export BEF
export AFT

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=$BEF a=$AFT s=$STR $FILE

问题是 nawk 命令的输出没有出现在屏幕上

>xgrep "bin/sh" * 0 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=0 a=3 s="bin/sh" *
#!/bin/sh

export AEGIS_PROJECT=$1
export EDITOR=cat
#!/bin/sh

aegis -cpu $pwd
aegis -dbu $1
#!/bin/sh
cd $HOME/ex_7/src/DTTCom
NRMan alphabuild clean
NRMan alphabuild library ex_7 8.19 app TEST DTTCom debug -j10
#!/bin/sh
cd $HOME/icx/src/DTTCom
NRMan alphabuild clean
NRMan alphabuild library icx_1 1.1 app TEST DTTCom debug -j10
#!/bin/sh
# *********************************************************
# This uses nawk to list lines coming prior to and after
# the given search string.

这是什么原因,我怎样才能让脚本工作?

4

1 回答 1

2

尝试使用:

xgrep "bin/sh" '*' 0 3

反而。

在将参数传递给脚本之前,通配符项的扩展发生在当前 shell 中,如下面的脚本所示:

pax: xgrep include *.c 0 3
#include <stdio.h>
gawk: (FILENAME=binmath.c FNR=1) fatal: division by zero attempted in '%'

pax: xgrep include '*.c' 0 3
#include <stdio.h>

// Prototypes - should go in separate header file.
void compBinNum (char*);
#include <stdio.h>
#include <string.h>
#include <string.h>

#define UTF8ERR_TOOSHORT -1
#define UTF8ERR_BADSTART -2
#include <stdio.h>
#include <errno.h>
#include <errno.h>

int main (void) {
    FILE *file = fopen ("words.txt", "r");

您可以看到这些参数如何与以下简单脚本和输出一起使用:

pax: cat argtest
    #!/bin/bash
    echo Number of arguments: $#
    echo Arguments: "$*"

pax: argtest *
    Number of arguments: 32
    Arguments: Makefile a.exe argtest binmath.c binmath.exe dev
        file.db infile input.txt inputfile limit10 output.txt
        p2.sh p2expected p2input1 p2input2 qq qq.c qq.cpp qq.exe
        qq.exe.stackdump qq.pl qq.py qqin qqq.c qqq.s tmpfile
        words2.txt xgrep xx.c xx.exe xx.pl

pax: argtest '*'
    Number of arguments: 1
    Arguments: *

更新:

根据您在评论中的问题:

谢谢。当我用单引号包裹文件时它起作用了。有没有一种方法可以在脚本中执行此操作,以便用户不必费心输入单引号?

不,那是因为 shell 在你的脚本看到它之前就已经完成了。但是,如果您将文件规范移动到命令行的末尾:

xgrep include 0 3 *.c

您可以修改您的脚本,使其不仅处理第 4 个参数,还处理之后的每个参数,一次一个。然后,当它们被外壳扩展时,就没有关系了。

类似的东西(gawk/nawk 在一行上):

STR=$1
BEF=$2
AFT=$3
while [[ ! -z "$4" ]] ; do
    echo ========== "$4"
    gawk '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=$BEF a=$AFT s=$STR "$4"
        | sed "s/^/$4: /"
    shift
done
echo ==========

让 shell 处理您的扩展并使用循环还允许您执行一些技巧,例如在输出的每个块(或行)中打印文件名:

pax: xgrep include  0 3 *.c
    ========== binmath.c
    binmath.c:     #include <stdio.h>
    binmath.c:
    binmath.c:     // Prototypes - should go in separate header file.
    binmath.c:     void compBinNum (char*);
    ========== qq.c
    qq.c:     #include <stdio.h>
    qq.c:     #include <string.h>
    qq.c:     #include <string.h>
    qq.c:
    qq.c:     #define UTF8ERR_TOOSHORT -1
    qq.c:     #define UTF8ERR_BADSTART -2
    ========== qqq.c
    ========== xx.c
    xx.c: #include <stdio.h>
    xx.c: #include <errno.h>
    xx.c: #include <errno.h>
    xx.c:
    xx.c: int main (void) {
    xx.c:     FILE *file = fopen ("words.txt", "r");
    ==========
于 2009-04-23T06:56:56.413 回答