Stampa l'output solo dopo aver trovato il motivo


13

C'è uno script (chiamiamolo così echoer) che stampa per schermare un mucchio di informazioni. Mi piacerebbe poter vedere le linee solo dopo aver trovato uno schema.

Immagino l'uso di una soluzione per assomigliare a qualcosa del genere

echoer | solution_command <pattern>

Idealmente patternsarebbe un'espressione regolare, ma per me le stringhe di valore elevato sarebbero sufficienti.


Quindi il modello può essere più stringhe?
Inian,

Un glob? Intendi un'espressione regolare? I globi hanno senso solo per le espansioni di nomi di file.
terdon

@Inian Non sono sicuro di aver capito la domanda. Intendi chiedere se voglio che funzioni con disgiunzioni?
user23146

Risposte:


21

AWK può farlo con intervalli di pattern, che consentono l'uso di qualsiasi espressione regolare:

echoer | awk '/pattern/,0'

stamperà echoerl'output a partire dalla corrispondenza della prima riga pattern.

AWK è basato su pattern e viene generalmente utilizzato con un approccio "se questo pattern corrisponde, esegui questo". "Questo modello" può essere un intervallo di modelli, definito come "quando questo modello corrisponde, iniziare a farlo, fino a quando questo altro modello corrisponde"; questo viene specificato scrivendo due motivi separati da una virgola, come sopra. I pattern possono essere corrispondenze di testo, come in /pattern/, in cui la riga corrente viene confrontata con il pattern, interpretata come un'espressione regolare; possono anche essere espressioni generali, valutate per ogni riga e considerate corrispondenti se il loro risultato è diverso da zero o non vuoto.

In AWK, l'azione predefinita è stampare la riga corrente.

Mettendo tutto questo insieme, awk '/pattern/,0'cerca le linee corrispondenti patterne, una volta trovata, applica l'azione predefinita a tutte le linee fino a quando la 0condizione corrisponde (è diversa da zero). awk '/pattern/,""'funzionerebbe anche.

Il manuale di Gawk è molto più dettagliato.


3
Non ero a conoscenza della semantica dell'intervallo con zero come fine dell'intervallo. Grazie!
Kusalananda

@StephenKitt Questo è fantastico! E se volessi stampare fino a quando non corrispondesse 0? Sarebbe /pattern/,/0/? Come sarebbe la risposta scrivendo esplicitamente l'azione predefinita?
user23146

@ user23146 sì, /pattern/,/0/stampa fino a quando non trova una riga (record) contenente "0". Scrivere lo snippet nella risposta con un'azione esplicita dà /pattern/,0 { print $0 }, o equivalentemente /pattern/,0 { print }.
Stephen Kitt,

7

L' sedequivalente obbligatorio di quello di @K StephenKitt awk:

sed '/pattern/,$!d'

patternviene interpretato come un'espressione regolare di base come in grep(al contrario dell'espressione regolare estesa in awk/ egrep/ grep -E). Alcune sedimplementazioni hanno un'opzione -E(BSD, ast, recente GNU / busybox, presto POSIX) o -r(GNU, ssed, busybox, alcune recenti BSD) per renderlo invece espressioni regolari estese e alcune hanno -P(ast) o -R(ssed) per farlo un'espressione regolare simile al perl.

Con perl:

perl -ne 'print if /pattern/ .. undef'

4

con GNU e * BSD grep:

grep -A1000000000 pattern file

A meno che il file non contenga più di 1 milione di righe, il gioco è fatto.


0

Se si utilizza un cercapersone come lessper visualizzare l'output dal comando

less +pattern

0

awk per le righe dopo (ma non incluso) la prima corrispondenza del modello

Se la riga contenente il modello di trigger è equivalente a "TAGLIA QUI", è possibile ometterla dall'output stampato:

echoer | awk 'flag ; /pattern/ { flag=1 }'

Ogni riga di input passa attraverso due componenti nel codice awk. Il primo componente è flag, che awk interpreta come "stampa la riga se la variabile flagè diversa da zero". Poiché le variabili awk sono 0 per impostazione predefinita, inizialmente non verrà stampato nulla.

Il secondo componente, /pattern/ { flag=1 }imposta il flag su 1 non appena rileva il pattern e il flag mantiene quel valore per il resto della corsa.

Quando viene rilevato per la prima volta il motivo, è passata l'opportunità di stampare quella linea di input. Verranno stampate tutte le righe successive (incluse le righe aggiuntive contenenti il ​​motivo).


0

bash

Un po 'goffo, ma funziona.

#!/bin/bash
found=false
while IFS= read -r; do
    if $found || [[ $REPLY =~ pattern ]]; then
        found=true
        printf '%s\n' "$REPLY"
    fi
done

Questa versione si basa cat, ma è più facile da capire.

#!/bin/bash
while IFS= read -r; do
    if [[ $REPLY =~ pattern ]]; then
        printf '%s\n' "$REPLY"
        break
    fi
done
cat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.