Come selezionare la prima occorrenza tra due schemi, inclusi quelli


27

Come posso selezionare la prima occorrenza tra due schemi, inclusi quelli. Preferibilmente usando sedo awk.

Io ho:

text
something P1 something
content1
content2
something P2 something
text
something P1 something
content3
content4
something P2 something
text

Voglio la prima occorrenza delle linee tra P1 e P2 (comprese le linee P1 e P2):

something P1 something
content1
content2
something P2 something

Risposte:


22
sed '/P1/,/P2/!d;/P2/q'

... farebbe il lavoro in modo portabile deliminando tutte le linee che !non rientrano nell'intervallo, quindi qeffettuando la prima volta che incontra la fine dell'intervallo. Non fallisce per P2 precedente a P1 e non richiede una sintassi specifica GNU per scrivere semplicemente.


Eccellente! Molto meglio del mio.
Muru,

1
@muru: spesso è più facile evitare contorsioni se si tenta di indirizzare l'autoprint: lasciare che il ciclo funzioni per te. Questa è l'abitudine in cui sono caduto comunque. Penso che sia probabilmente meglio descritto come una prugna contro un metodo selezionato - tendo a finire negando uno schema piuttosto che cercarlo.
Mikeserv,

Ciò si bloccherà durante l'elaborazione di fileSize di grandi dimensioni.
Brain90,

@ Brain90 - shouldnt. se riesci a riprodurre in modo affidabile il tuo reclamo, dovresti rivolgerti al manutentore del tuo sed... questo è un bug nella tua sedesecuzione e non nello script sopra.
mikeserv,

1
@mikeserv Non lo avrei detto se non lo fossi. La tua preoccupazione sul fatto che mi interessi o meno di un paio di personaggi è strana: ho osservato che l'espressione sed ha funzionato sia con che senza /P2/qsul mio sistema; questo è tutto. Ero curioso di qualcosa e volevo condividere ciò che ho trovato.
Alexej Magura,

8

con awk

awk '/P1/{a=1};a;/P2/{exit}' file
something P1 something
content1
content2
something P2 something

8

In sed:

sed -n '/P1/,/P2/p; /P2/q'
  • -nsopprime la stampa predefinita e si stampano le righe tra gli intervalli di indirizzi corrispondenti utilizzando il pcomando.
  • Normalmente questo corrisponderebbe ad entrambe le sezioni, quindi esci ( q) quando le prime P2corrispondono.

Questo fallirà se P2viene prima P1. Per gestire quel caso, prova:

sed -n '/P1/,/P2/{p; /P2/q}'

1
Non sono d'accordo; La risposta di Mikeserv non è migliore della tua.
G-Man dice "Reinstate Monica" il

@ g-man - pshaw. ma stavo solo pensando la stessa cosa.
Mikeserv,

1
@gman - no. ora capisco. miniere molto meglio. no {stack}!
Mikeserv,

1

Se vuoi saltare i pattern stessi, ecco la awkversione:

awk '/P2/ {exit} /P1/ {f=1; next} f' file

Per me va bene. Potresti aggiungere qualche informazione in più su come funziona il comando?
0xAffe

1

Una semplice awksoluzione di (in ordine-di a metà strada tra la risposta di Iruvar e  la risposta di Muru , ma non utilizzando una variabile):

awk '/P1/,/P2/ { print }  /P2/ { exit }'

e, come notato da Muru, se il primo P2 appare prima del primo P1, questo non stampa nulla.

Naturalmente, se si desidera stampare tutte le gamme P1-P2:

something P1 something
content1
content2
something P2 something
something P1 something
content3
content4
something P2 something

lascia fuori la exitparte:

awk '/P1/,/P2/ { print }'

1
awk '/P1/,/P2/{print;f=1} f&&/P2/{exit}' data

Esci immediatamente dopo la stampa, non prima.


0

Per saltare i pattern stessi e mostrare solo il primo blocco corrispondente in una singola GNU sed:

sed -nre '/STARTPATTERN/ {:a;n;/ENDPATTERN/{b;};p;ba}' file
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.