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 sedsaja membawa penghitungan iskejadian dari satu baris ke yang berikutnya. Ini seharusnya dapat menangani sebanyak mungkin ises per baris saat Anda melemparkannya, dan itu tidak perlu buffer garis lama sementara itu - itu hanya mempertahankan satu karakter baris baru untuk setiap isyang 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 ises yang valid dengan memasukkan \ngaris sebelum sebelum semua kejadian isyang mendahului nol atau satu karakter tanda baca diikuti oleh spasi. Itu lulus lain dan menghapus semua \newline yang segera didahului oleh karakter bukan spasi. Penanda yang ditinggalkan ini akan cocok is.dan istetapi tidak thisatau ?is.
Selanjutnya mengumpulkan setiap penanda ke ekor tali - untuk setiap \nipertandingan pada garis itu menambahkan \ngaris ke ekor tali dan menggantinya dengan salah satu iatau u. Jika ada 3 \nbaris 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 lperintah 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 ises 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