【问题标题】:Script with nawk doesn't print output to screen带有 nawk 的脚本不会将输出打印到屏幕
【发布时间】:2010-10-21 07:12:42
【问题描述】:

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

# *********************************************************
# 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.

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

【问题讨论】:

    标签: shell nawk


    【解决方案1】:

    尝试使用:

    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: *
    

    更新:

    根据您在 cmets 中的问题:

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

    不,那是因为 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");
        ==========
    

    【讨论】:

    • 谢谢。当我用''包裹“文件”时它起作用了。有没有办法可以在脚本中执行此操作,以便用户不必费心输入单引号?
    • 如何更改 "sed "s/^/$4: /" 以打印文件的行号?
    • sed 不能这样做,因为该信息已经消失,您必须使用 awk 生成它。在我的脑海中,“b{r[NR%b]=$0}”部分将变成类似于“b{r[NR%b]=NR + "> " + $0}" (未经测试的语法,我无权从当前位置访问 awk)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多