p='[:punct:]' s='[:space:]'
sed -Ee'1!{/\n/!b' -e\} \
-e's/(\n*)(.*)/ \2 \1/' \
-e"s/is[$p]?[$s]/\n&/g" \
-e"s/([^$s])\n/\1/g;1G" \
-e:c -e"s/\ni(.* )\n{3}/u\1/" \
-e"/\n$/!s/\n//g;/\ni/G" \
-e's//i/;//tc' \
-e's/^ (.*) /\1/;P;$d;N;D'
Quel po ' sed
porta solo un conteggio delle is
occorrenze da una riga all'altra. Dovrebbe gestire in modo affidabile tutti gli is
es per riga che ci si lancia, e non ha bisogno di bufferizzare le vecchie linee mentre lo fa - mantiene solo un singolo carattere di nuova riga per ogni cosa is
che incontra che non fa parte di un'altra parola.
Il risultato è che modificherà solo la terza occorrenza in un file e conterrà conteggi per riga. Quindi se un file appare come:
1. is is isis
2. is does
... stamperà ...
1. is is isis
2. us does
Per prima cosa gestisce i casi limite inserendo uno spazio nella testa e nella coda di ogni linea. Ciò rende un po 'più facile accertare i confini delle parole.
Quindi cerca is
es validi inserendo una \n
ewline prima di tutte le occorrenze is
che precedono immediatamente zero o un carattere di punteggiatura seguito da uno spazio. \n
Esegue un altro passaggio e rimuove tutte le ewline immediatamente precedute da un carattere non spaziale. Questi marcatori lasciati indietro corrisponderanno is.
e is
ma non this
o ?is
.
Successivamente raccoglie ciascun marcatore alla coda della stringa: per ogni \ni
corrispondenza su una linea, aggiunge una \n
ewline alla coda della stringa e la sostituisce con una i
o u
. Se ci sono 3 \n
ewline di fila raccolte nella coda della stringa, allora usa u - altrimenti l'i. La prima volta che si usa au è anche l'ultimo: la sostituzione avvia un ciclo infinito che si riduce a get line, print line, get line, print line,
così via.
Alla fine di ogni ciclo del ciclo di prova, pulisce gli spazi inseriti, stampa solo fino alla prima nuova riga presente nello spazio del motivo e riparte.
Aggiungerò un l
comando ook in testa al ciclo come:
l; s/\ni(.* )\n{9}/u\1/...
... e dai un'occhiata a cosa fa mentre funziona con questo input:
hai this is linux.
hai this is unix.
hai this is mac.
hai this is unchanged is.
... quindi ecco cosa fa:
hai this \nis linux. \n$ #behind the scenes
hai this is linux. #actually printed
hai this \nis unix. \n\n$ #it builds the marker string
hai this is unix.
\n\n\n$ #only for lines matching the
\n\n\n$ #pattern - and not otherwise.
hai this \nis mac. \n\n\n$ #here's the match - 3 ises so far in file.
hai this us mac. #printed
hai this is unchanged is. #no look here - this line is never evaled
Ha più senso forse con più is
es per riga:
nthword()( p='[:punct:]' s='[:space:]'
sed -e '1!{/\n/!b' -e\} \
-e 's/\(\n*\)\(.*\)/ \2 \1/' \
-e "s/$1[$p]\{0,1\}[$s]/\n&/g" \
-e "s/\([^$s]\)\n/\1/g;1G;:c" \
-e "${dbg+l;}s/\n$1\(.* \)\n\{$3\}/$2\1/" \
-e '/\n$/!s/\n//g;/\n'"$1/G" \
-e "s//$1/;//tc" -e 's/^ \(.*\) /\1/' \
-e 'P;$d;N;D'
)
È praticamente la stessa cosa, ma scritto con POSIX BRE e una rudimentale gestione degli argomenti.
printf 'is is. is? this is%.0s\n' {1..4} | nthword is us 12
...prende...
is is. is? this is
is is. is? this is
is is. is? this us
is is. is? this is
... e se abilito ${dbg}
:
printf 'is is. is? this is%.0s\n' {1..4} |
dbg=1 nthword is us 12
... possiamo vederlo iterare ...
\nis \nis. \nis? this \nis \n$
is \nis. \nis? this \nis \n\n$
is is. \nis? this \nis \n\n\n$
is is. is? this \nis \n\n\n\n$
is is. is? this is
\nis \nis. \nis? this \nis \n\n\n\n\n$
is \nis. \nis? this \nis \n\n\n\n\n\n$
is is. \nis? this \nis \n\n\n\n\n\n\n$
is is. is? this \nis \n\n\n\n\n\n\n\n$
is is. is? this is
\nis \nis. \nis? this \nis \n\n\n\n\n\n\n\n\n$
is \nis. \nis? this \nis \n\n\n\n\n\n\n\n\n\n$
is is. \nis? this \nis \n\n\n\n\n\n\n\n\n\n\n$
is is. is? this \nis \n\n\n\n\n\n\n\n\n\n\n\n$
is is. is? this us
is is. is? this is