2009-04-23 3 views
2

Ich bin auf einen netten Einzeiler gestoßen, um nach Text zu suchen und die Ergebnisse mit einer gegebenen Anzahl von nachfolgenden und folgenden Zeilen auszudrucken. Ich versuche ein Skript daraus zu erstellen. Bisher ist es das, was ich habe:Skript mit nawk druckt keine Ausgabe auf Bildschirm

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

Das Problem ist, dass der Ausgang des nawk Befehls nicht auf dem Bildschirm angezeigt werden

>xgrep "bin/sh" * 0 3 
> 

Aber wenn ich in dem Befehl eingeben, erhalte ich ein richtiger Ausgang:

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

Was ist der Grund dafür und wie kann ich das Skript zum Funktionieren bringen?

Antwort

2

Versuchen Sie es mit:

xgrep "bin/sh" '*' 0 3 

statt.

Die Erweiterung des Wildcard-Begriff wird in der aktuellen Shell geschieht, bevor die Argumente an das Skript übergeben werden, wie in diesem Transkript gezeigt:

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"); 

Sie können sehen, wie diese Argumente mit dem folgenden einfachen Skript arbeiten und Ausgang:

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

Update:

auf Ihre Frage mit Sitz in der Kommentare:

Danke. Es funktionierte, als ich die Datei in einfache Anführungszeichen verpackte. Gibt es eine Möglichkeit, dies innerhalb des Skripts zu tun, so dass der Benutzer sich nicht mit einfachen Anführungszeichen beschäftigen muss?

Nein, das liegt daran, dass die Shell es tut, bevor Ihr Skript es jemals sieht. Wenn Sie jedoch die Dateispezifikation bis zum Ende der Befehlszeile bewegen somit:

xgrep include 0 3 *.c 

Sie Ihr Skript nicht nur Prozess Argument Nummer 4, aber jedes Argument danach auch ändern könnte, einen nach dem anderen . Dann, wenn sie durch die Shell erweitert wurden, ist es egal.

So etwas wie (mit gawk/nawk auf einer einzigen Zeile):

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 ========== 

Letting die Schale Erweiterungshandhaben und mit einer Schleife ermöglicht es Ihnen auch Tricks zu tun, wie das Drucken der Dateiname mit jedem Block (oder Zeile) der Ausgabe:

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"); 
    ========== 
+0

Danke. Es funktionierte, als ich die "Datei" mit "" umhüllte. Gibt es eine Möglichkeit, dies innerhalb des Skripts zu tun, so dass der Benutzer sich nicht mit einfachen Anführungszeichen beschäftigen muss? – Gayan

+0

Siehe Update, @Gayan. – paxdiablo

+0

Wie kann ich "sed" s/^/$ 4:/"ändern, um die Zeilennummer der Datei zu drucken? – Gayan