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'
Sedikit sed
saja membawa penghitungan is
kejadian dari satu baris ke yang berikutnya. Ini seharusnya dapat menangani sebanyak mungkin is
es per baris saat Anda melemparkannya, dan itu tidak perlu buffer garis lama sementara itu - itu hanya mempertahankan satu karakter baris baru untuk setiap is
yang ia temui yang bukan bagian dari kata lain.
Hasilnya adalah ia akan memodifikasi hanya kejadian ketiga dalam file - dan itu akan membawa jumlah per baris. Jadi jika sebuah file terlihat seperti:
1. is is isis
2. is does
... itu akan mencetak ...
1. is is isis
2. us does
Pertama-tama menangani kasing tepi dengan memasukkan spasi di kepala dan ekor setiap garis. Ini membuat batasan kata sedikit lebih mudah untuk dipastikan.
Selanjutnya mencari is
es yang valid dengan memasukkan \n
garis sebelum sebelum semua kejadian is
yang mendahului nol atau satu karakter tanda baca diikuti oleh spasi. Itu lulus lain dan menghapus semua \n
ewline yang segera didahului oleh karakter bukan spasi. Penanda yang ditinggalkan ini akan cocok is.
dan is
tetapi tidak this
atau ?is
.
Selanjutnya mengumpulkan setiap penanda ke ekor tali - untuk setiap \ni
pertandingan pada garis itu menambahkan \n
garis ke ekor tali dan menggantinya dengan salah satu i
atau u
. Jika ada 3 \n
baris dalam satu baris berkumpul di ujung string maka ia menggunakan u - selain itu i. Au pertama kali digunakan juga yang terakhir - penggantian memicu loop tak terbatas yang bermuara ke get line, print line, get line, print line,
dan seterusnya.
Pada akhir setiap siklus loop coba, ia membersihkan ruang yang disisipkan, mencetak hanya hingga baris baru yang pertama kali terjadi dalam ruang pola, dan berjalan lagi.
Saya akan menambahkan l
perintah ook di bagian atas loop seperti:
l; s/\ni(.* )\n{9}/u\1/...
... dan lihat apa fungsinya saat bekerja dengan input ini:
hai this is linux.
hai this is unix.
hai this is mac.
hai this is unchanged is.
... jadi inilah fungsinya:
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
Lebih masuk akal mungkin dengan lebih banyak is
es per baris:
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'
)
Praktis hal yang sama tetapi ditulis dengan POSIX BRE dan penanganan argumen yang belum sempurna.
printf 'is is. is? this is%.0s\n' {1..4} | nthword is us 12
...mendapat...
is is. is? this is
is is. is? this is
is is. is? this us
is is. is? this is
... dan jika saya mengaktifkan ${dbg}
:
printf 'is is. is? this is%.0s\n' {1..4} |
dbg=1 nthword is us 12
... kita bisa menontonnya iterate ...
\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