Se qualifichi una parola per indicare una sequenza di 1 o più caratteri non vuoti, la risposta è sicuramente sì, ed è anche molto semplice. Questo perché [[:blank:]]*
e [^[:blank:]]*
sono complementi booleani e - purché tutti i caratteri in una stringa siano completi - [[:blank:]]*
U [^[:blank:]]*
può descrivere qualsiasi stringa possibile allo stesso modo .*
.
Se all'interno di una stringa esiste un carattere incompleto o una sequenza di byte altrimenti non valida, nessuno dei due può descriverlo con esattezza, come talvolta accade quando si interpreta una stringa con una codifica errata. Per garantire un carattere completo per byte in qualsiasi stringa, la locale C può essere forzata come:
LC_ALL=C sed ...
... che eviterebbe qualsiasi problema che descriva la corda dalla testa alla coda con un modello tutto compreso come .*
o([ ]*[^ ]*)*
Un modello completamente complementare può ripetere tutte le volte che è necessario da sinistra a destra la lunghezza di qualsiasi stringa per atterrare sull'ultima occorrenza possibile senza alcuna interruzione nel modello. Questo è, in definitiva, un linguaggio regolare.
BRE:
sed 's/\(\([^[:blank:]]*\)[[:blank:]]*\)*/\2/'
ERE:
sed -E 's/(([^[:blank:]]*)[[:blank:]]*)*/\2/'
Entrambe queste versioni stamperanno comunque righe vuote, e questo perché la *
stella di Kleene corrisponde a zero o più occorrenze di un motivo. Prima corrisponde a zero o più caratteri non vuoti, quindi zero o più caratteri vuoti, quindi zero o più occorrenze delle corrispondenze raggruppate fino a quando non corrisponde alla stringa nella sua interezza.
Avendo abbinato tutto questo, la magia accade nella sostituzione: i riferimenti restituiti dai gruppi \1
e \2
sono le ultime occorrenze di ciascuno. Pertanto, quando viene effettuata la sostituzione, tutta la stringa viene sostituita con solo l'ultima occorrenza su una riga di zero o più caratteri non vuoti o sul sottogruppo \2
.
Ovviamente questo funziona per ogni possibile stringa, anche vuota, il che significa che entrambi i moduli stamperanno i caratteri di nuova riga per le righe che contengono solo caratteri vuoti o nessuno. Per gestirlo ci sono un paio di cose che puoi fare, ma prima rendiamo la classe di caratteri un po 'più facile da scrivere:
b='[:blank:]'
Ora, per stampare solo se una riga contiene uno o più caratteri non vuoti puoi fare:
BRE:
sed -n "s/\(\([^$b]*\)[$b]*\)*/\2/;/./p"
ERE:
sed -En "/[^$b]/s/(([^$b]*)[$b]*)*/\2/p"
- Caso BRE: la sostituzione viene sempre eseguita e vengono stampati solo gli spazi modello con almeno un carattere rimanente.
- Caso ERE: la sostituzione viene sempre e solo tentata su uno spazio modello contenente almeno un carattere non vuoto.
Entrambe le forme funzioneranno con entrambi i metodi, purché la sintassi sia corretta.
L' opzione -n
disabilita la stampa automatica dello spazio del motivo e il p
flag sui comandi s///
ubstitution o /
address /
stampa i suoi risultati solo in caso di successo.
Questa stessa logica può essere applicata per ottenere qualsiasi {num}
occorrenza, come ad esempio:
BRE:
sed -n "s/\([$b]*\([^$b]\{1,\}\)\)\{num\}.*/\2/p"
ERE:
sed -En "s/([$b]*([^$b]+)){num}.*/\2/p"
... in cui num
entrambe le regexps possono essere sostituite con un numero per stampare solo la {num}
ricorrenza specificata di una sequenza di caratteri non vuoti. Qui viene utilizzata una forma leggermente diversa per garantire che il conteggio non sia distorto per lo spazio iniziale in una stringa.
Si noti che il -E
passaggio ERE su sed
è supportato nelle versioni BSD e GNU, sebbene non sia ancora una sintassi standard POSIX.
sed
?