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

代わりは。

次のトランスクリプトに示すように、引数がスクリプトに渡される前に、現在のシェルでワイルドカード用語の展開が行われています。

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

アップデート:

コメントの質問に基づいて:

ありがとう。ファイルを一重引用符で囲むとうまくいきました。ユーザーが一重引用符を入力する必要がないように、スクリプト内でこれを行う方法はありますか?

いいえ、それは、スクリプトが認識する前にシェルが実行しているためです。ただし、ファイル指定をコマンド ラインの末尾に移動すると、次のようになります。

xgrep include 0 3 *.c

引数番号 4 だけでなく、それ以降のすべての引数も一度に 1 つずつ処理するようにスクリプトを変更できます。その後、シェルによって展開されたときは問題ありません。

次のようなもの (1 行に 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 ==========

シェルに展開を処理させ、ループを使用すると、出力の各ブロック (または行) でファイル名を出力するなどのトリックを行うこともできます。

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 に答える