sed
L'API è primitiva - e questo è di progettazione. Almeno, è rimasto primitivo dal design - non posso dire se sia stato progettato in modo primitivo all'inizio. Nella maggior parte dei casi, la scrittura di uno sed
script che, quando eseguito, produrrà un altro sed
script è davvero una questione semplice. sed
viene molto spesso applicato in questo modo da preprocessori macro come m4
e / o make
.
(Quello che segue è un caso d'uso altamente ipotetico: è un problema progettato per soddisfare una soluzione. Se ti sembra un allungamento, probabilmente è perché lo è, ma ciò non lo rende necessariamente meno valido.)
Considera il seguente file di input:
cat <<"" >./infile
camel
cat dog camel
dog cat
switch
upper
lower
Se volessimo scrivere uno sed
script che aggiungesse la parola -case alla coda di ogni parola appropriata nel file di input sopra riportato solo se potesse essere trovato su una riga in un contesto appropriato , e avremmo voluto farlo nel modo più efficiente possibile ( come dovrebbe essere il nostro obiettivo, ad esempio, durante un'operazione di compilazione), allora dovremmo preferire evitare di applicare /
regexp /
s il più possibile.
Una cosa che potremmo fare è pre-modificare il file sul nostro sistema in questo momento e non chiamare mai sed
durante la compilazione. Ma se una qualsiasi di quelle parole nel file dovesse o non dovesse essere inclusa in base alle impostazioni locali e / o alle opzioni di compilazione, probabilmente non sarebbe un'alternativa desiderabile.
Un'altra cosa che potremmo fare è elaborare il file ora contro regexps. Siamo in grado di produrre - e includere nella nostra compilation - uno sed
script che può applicare le modifiche in base al numero di riga - che in genere è un percorso molto più efficiente nel lungo periodo.
Per esempio:
n=$(printf '\\\n\t')
grep -En 'camel|upper|lower' <infile |
sed " 1i${n%?}#!/usr/heirloom/bin/posix2001/sed -nf
s/[^:]*/:&$n&!n;&!b&$n&/;s/://2;\$a${n%?}q"'
s/ *cat/!/g;s/ *dog/!/g
s| *\([cul][^ ]*\).*|s/.*/\1-case/p|'
... che scrive l'output sotto forma di uno sed
script e che sembra ...
#!/usr/heirloom/bin/posix2001/sed -nf
:1
1!n;1!b1
1s/.*/camel-case/p
:2
2!n;2!b2
2!!s/.*/camel-case/p
:5
5!n;5!b5
5s/.*/upper-case/p
:6
6!n;6!b6
6s/.*/lower-case/p
q
Quando quell'output viene salvato in un file di testo eseguibile sul mio computer chiamato ./bang.sed
ed eseguito come ./bang.sed ./infile
, l'output è:
camel-case
upper-case
lower-case
Ora potresti chiedermi ... Perché dovrei farlo? Perché non dovrei semplicemente ancorare grep
le partite? Chi usa comunque la custodia per cammelli? E a ogni domanda a cui ho potuto solo rispondere, non ho idea ... perché non lo so. Prima di leggere questa domanda non avevo mai notato personalmente il multi-! requisito di analisi nelle specifiche - Penso che sia una cattura piuttosto ordinata.
Il multi-! la cosa ha immediatamente avuto un senso per me, però - gran parte delle sed
specifiche è orientata verso script semplicemente analizzati e semplicemente generati sed
. Probabilmente troverai i \n
delimitatori di ewline richiesti per [wr:bt{]
avere molto più senso in quel contesto, e se tieni a mente quell'idea potresti dare un senso migliore ad alcuni altri aspetti delle specifiche - (come l' :
accettazione di indirizzi e il q
rifiuto di accetta non più di 1) .
Nell'esempio di cui sopra che scrivo una certa forma di sed
script che può solo sempre essere letto una volta. Se lo guardi con attenzione, potresti notare che mentre sed
legge il file di modifica passa da un blocco di comandi al successivo - non si discosta mai o completa il suo script di modifica fino a quando non è completamente finito con il suo file di modifica.
Lo considero multi-! gli indirizzi potrebbero essere più utili in quel contesto che in alcuni altri, ma, onestamente, non riesco a pensare a un singolo caso in cui avrei potuto sfruttarlo molto bene - e io sed
molto. Penso anche che sia degno di nota che sed
entrambi GNU / BSD non riescano a gestirlo come specificato - questo probabilmente non è un aspetto della specifica che è molto richiesto, e quindi se un'implementazione lo trascura dubito molto seriamente che i loro bug @ box ne soffriranno di conseguenza terribilmente.
Detto questo, la mancata gestione di questo come specificato è un bug per qualsiasi implementazione che pretende di essere conforme, e quindi penso che sia necessario sparare un'e-mail alle relative caselle di sviluppo qui, e intendo farlo in caso contrario.
!
agisce come un interruttore,/pattern/!!
è uguale a/pattern/
ed/pattern/!!!
è uguale a/pattern/!
. Su FreeBSD i multipli!
sono gli stessi di uno singolo.