2017-09-21 1 views
-1

J'ai un fichier qui ressemble au-dessous -awk pour retourner toutes les lignes correspondant à

A 
B 
C 
D 
E 

----- 

A 
B 
C 
D 
C 

--- 

X 
Y 
A 
B 
XEC 

--- 

Lorsque la cinquième ligne de chaque bloc est/contient E, je veux que les 4 lignes précédentes à retourner. J'ai écrit la commande ci-dessous, mais il est buggé

awk '{a[NR]=$0} $0~s {f=NR} END {print a[f-4]; print a[f-6]; print a[f-8];}' s="E" file.txt 

Mais il ne retourne que la dernière correspondance. Je veux que toutes les lignes correspondantes soient renvoyées.

Pour les entrées ci-dessus, la sortie doit être

A 
B 
C 
D 
--- 

X 
Y 
A 
B 

est-il un autre moyen d'y parvenir?

+0

Avez-vous vraiment ** '' --- ** lignes dans le fichier, comme indiqué en question? – anubhava

+0

Oui, j'ai ces lignes :) – maddie

Répondre

3

En utilisant gawk: RS multi-caractères est uniquement pris en charge dans gnu-awk

awk -v RS='\n\n[-]+\n\n*' -v FS="\n" '$5 ~ /E/{printf "%s\n%s\n%s\n%s\n---\n",$1,$2,$3,$4}' inputfile 
A 
B 
C 
D 
--- 
X 
Y 
A 
B 
--- 
+1

++ mais ne mentionne plusieurs caractères RS est seulement pris en charge dans gnu-awk – anubhava

3

Je ne sais pas vraiment comment vous voulez, vous avez vraiment besoin --- puis ??? omble nouvelle ligne

En utilisant tac et awk vous pouvez essayer ci-dessous un

  • Imprimer les N enregistrements après quelques regexp:

    awk -v n=4 'c&&c--;/regexp/{c=n}' <input_file>

  • Imprimer les N enregistrements avant que certains regexp:

    tac <input_file> | awk -v n=4 'c&&c--;/regexp/{c=n}' | tac

    ^     ^   ^   ^
    |      |    |    | 
    reverse file no of lines to print when regexp found again reverse 
    

entrée

$ cat infile 
A 
B 
C 
D 
E 

----- 

A 
B 
C 
D 
C 

--- 

X 
Y 
A 
B 
XEC 

--- 

Lorsque n=4

$ tac infile | awk -v n=4 'c&&c--;/E/{c=n}' | tac 
A 
B 
C 
D 
X 
Y 
A 
B 

Lorsque n=2

$ tac infile | awk -v n=2 'c&&c--;/E/{c=n}' | tac 
C 
D 
A 
B 
+0

Je voudrais un séparateur entre les entrées pour le traitement ultérieur du fichier. Merci pour votre commande, je vais essayer. – maddie

+0

@maddie essayer 'tac infile | awk -v n = 4 'c == n {print "---"} c &&c--;/E/{c = n}' | tac' –

+1

++ bon usage de 'tac' – anubhava

0

une autre awk (avec seulement awk simple):

awk ' 
/^-/ && !prev{ 
    print; 
    count=val=""; 
    prev=$0; 
    next 
} 
/^-/ && prev{ 
    count=val=""; 
    prev=$0; 
    next 
} 
/^ /{ 
    count=val=""; 
    next 
} 
NF && (\ 
    ++count==5 && $0~/E/){ 
    print val RS $0; 
    val=count="" 
} 
{ 
    val=val?val ORS $0:$0; 
} 
' Input_file 

sortie sera la suivante.

A 
B 
C 
D 
E 
----- 
X 
Y 
A 
B 
XEC 

Explication des awk:

awk ' 
/^-/ && !prev{   ##Checking conditions here if any line starts with -(dash) and variable named prev is NULL. 
    print;     ##printing the current line. 
    count=val="";   ##Making variables count and val to NULL now. 
    prev=$0;    ##Assigning the current line value to variable prev now. 
    next     ##Using next will skip all further statements. 
} 
/^-/ && prev{   ##Checking conditions if a line starts from -(dash) and variable prev value is NOT NULL. 
    count=val="";   ##Making values of variables named count and val to NULL. 
    prev=$0;    ##Assigning variable prev to current line. 
    next     ##Using next will skip all further statements. 
} 
/^ /{     ##Checking condition here if a line starts with space. 
    count=val="";   ##Making variables named count and val to NULL. 
    next     ##Using next will skip all further statements. 
} 
NF && (\ 
    ++count==5 && $0~/E/){ ##Checking conditions if a line has value of NF(means not a blank line) and variable count(whose value is pre-increasing to 1 each time cursor comes here) is equal to 5 and current line has capital E in it then do following. 
    print val RS $0; ##printing variable named val and RS(record separator) with current line. 
    val=count=""  ##Nullifying the variables named val and count here. 
} 
{ 
    val=val?val ORS $0:$0; ##Creating a variable named val and its value is concatenating to itself. 
} 
' Input_file    ##Mentioning the Input_file name here.