Stampa linee tra (ed escludendo) due motivi


13

Ho intenzione di inviare il modulo utilizzando cURL, dove alcuni dei contenuti provengono da altri file, selezionati utilizzando sed

Se param1si utilizza il modello di corrispondenza delle linee di un altro file sed, il comando seguente funziona correttamente:

curl -d param1="$(sed -n '/matchpattern/p' file.txt)" -d param2=value2 http://example.com/submit

Ora vai al problema. Voglio mostrare solo il testo tra 2 pattern di corrispondenza escluso il pattern di corrispondenza stesso.

Diciamo che file.txtcontiene:

Bla bla bla
firstmatch
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
secondmatch
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

Attualmente, molti sedcomandi "tra 2 schemi corrispondenti" non verranno rimossi firstmatche secondmatch.

Voglio che il risultato diventi:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.

Risposte:


15

Ecco un modo per farlo:

sed '1,/firstmatch/d;/secondmatch/,$d' 

Ha spiegato: Dalla prima linea per la linea di corrispondenza firstmatch , eliminare. Dalla riga corrispondente alla seconda corrispondenza all'ultima riga, elimina.



5

L'altra sedsoluzione fallirà se si firstmatchverifica sulla 1a riga 1 .

Mantieni la semplicità, usa un singolo intervallo e un regex 2 vuoto :
o stampa tutto in quell'intervallo escludendo le estremità dell'intervallo (stampa automatica disabilitata) 3 :

sed -n '/firstmatch/,/secondmatch/{//!p;}' infile

o, più breve, elimina tutto ciò che non rientra in quell'intervallo e cancella anche le estremità dell'intervallo:

sed '/firstmatch/,/secondmatch/!d;//d' infile


1: Il motivo è che se il secondo indirizzo è una regexp, il controllo della corrispondenza finale inizierà con la riga che segue la riga che corrisponde al primo indirizzo .
Pertanto, /firstmatch/non viene mai valutato per la 1a riga dell'input, sedlo eliminerà semplicemente in quanto corrisponde al numero di riga 1,/RE/e passerà alla 2a riga dove controlla se la riga corrisponde/firstpattern/

2: Quando un REGEX è vuoto (cioè //) sedsi comporta come se fosse stato specificato l'ultimo REGEX utilizzato nell'ultimo comando applicato (come indirizzo o come parte di un comando sostitutivo).

3: la ;}sintassi è per sedimplementazioni moderne ; con quelli più vecchi utilizzare una nuova riga anziché il punto e virgola o espressioni separate, ad essed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile


Puoi spiegare cosa //sta facendo (dentro {…})?
G-Man dice "Ripristina Monica" il

Grazie, ma sei caduto nella mia trappola. So che //significa che è stata utilizzata l'ultima espressione regolare; da tutto quello che ho letto, dovrebbe essere /secondmatch/. Ho verificato attraverso i test che il tuo comando funziona e quindi ho concluso che funziona come /firstmatch|secondmatch/(che hai confermato), ma non riesco a trovare alcuna documentazione (nemmeno il documento POSIX a cui hai collegato o la GNU sed manuale ) che descrive questo comportamento. ... (proseguendo)
G-Man dice "Ripristina Monica" il

(Proseguendo) ... Esperimenti divertenti: (I) In sed: (1) Se lo faccio /first/,4, allora //agisco come /first/. (2) Se lo faccio 2,/second/, //viene visualizzato l'errore "nessuna espressione regolare precedente". (Trovo che questo sia un palese fallimento nel seguire il comportamento specificato.) (3) L'aggiunta --posixnon cambia nessuna delle precedenti. (II) In altri programmi: (4) In vi, after /first/,/second/, si //comporta come /second/(e le altre forme sono anche implementazioni razionali della regola documentata). ... (proseguendo)
G-Man dice "Ripristina Monica" il

(Proseguendo) ... (5)  awksembra non avere alcuna nozione di "l'ultimo RE usato"; //si riferisce al non carattere prima o dopo qualsiasi personaggio. (Ti invito a provare echo -- | awk '{ gsub(//, "cha"); print }'.)
G-Man dice 'Reinstate Monica' il

Quindi, leggi "l'ultimo REGEX utilizzato nell'ultimo comando" come "l'ultimo REGEX (s) utilizzato nell'ultimo comando" e quindi hai (correttamente) indovinato che significava /first|second/. Sei fortunato. Cito gli altri programmi per dimostrare che questa non è una convenzione regex a livello di sistema. Chiunque l'abbia aggiunto sednon si è preso la briga di aggiungerlo vim, dove avrebbe avuto lo stesso senso. :-) ⁠
G-Man dice "Ripristina Monica" il
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.