Saya memiliki banyak file txt, saya ingin menampilkannya dengan huruf kecil, hanya alfabet dan satu kata per baris, saya bisa melakukannya dengan beberapa tr
perintah dalam pipa seperti ini:
tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'
Apakah mungkin melakukan ini dalam satu pemindaian? Aku bisa menulis sebuah program C untuk melakukan hal ini, tapi aku merasa seperti ada cara untuk melakukannya dengan menggunakan tr
, sed
, awk
atau perl
.
Jawaban:
Anda dapat menggabungkan beberapa terjemahan (kecuali kasus kompleks yang melibatkan set yang bergantung pada lokal yang tumpang tindih), tetapi Anda tidak dapat menggabungkan penghapusan dengan terjemahan.
Dua panggilan ke
tr
cenderung lebih cepat daripada satu panggilan ke alat yang lebih kompleks, tetapi ini sangat tergantung pada ukuran input, pada proporsi karakter yang berbeda, pada implementasitr
dan alat yang bersaing, pada sistem operasi, pada nomor inti, dll.sumber
tr -s '[:upper:] [:punct:]' '[:lower:]\n' <doyle_sherlock_holmes.txt
printf 'A.AAAA,A' | tr -s '[:upper:] [:punct:]' '[:lower:][\n*]'
dapatkana\na\na'
, dan transformasi untuk... '[:lower:]\n'
mungkin tidak perlu melakukan apa pun untuk'[:punct:]'
tetap - beberapatr
s akan memotong set1 untuk mencocokkan 2 dan beberapa akan melakukan yang tersirat[\n*]
. Lebih baik hanya menggunakan rentang di sana.Berikut ini beberapa pendekatan:
GNU
grep
dantr
: temukan semua kata dan buat huruf kecilGNU grep dan perl: seperti di atas tetapi perl menangani konversi ke huruf kecil
perl: temukan semua karakter alfabet dan cetak dalam huruf kecil (terima kasih @steeldriver):
sed: hapus semua karakter yang bukan alfabet atau spasi, gantikan semua karakter alfabet dengan versi huruf kecilnya dan ganti semua spasi dengan baris baru. Perhatikan bahwa ini mengasumsikan bahwa semua spasi putih adalah spasi, tidak ada tab.
sumber
perl -lne 'print lc for /[[:alpha:]]+/g'
juga berfungsi? atau itu gaya yang buruk? (Saya baru perl dan mencoba belajar!)sed -z 's/\W*\(\w\+\)\W*/\L\1\n/g'
sed
bisa lakukan\w
sekarang? Keren!sed
's-z
ero membatasi switch - itu siklus lebih\0NUL
s daripada baris baru. Cukup keren ketika Anda melakukan sesuatu sepertitar -c . | tr -s \\0 | sed -z ...
- tetapi agak lambat.Iya. Anda dapat melakukannya
tr
dengan lokal ASCII (yang, untuk GNUtr
, jenis dari satu-satunya ruang lingkupnya) . Anda bisa menggunakan kelas POSIX, atau Anda bisa mereferensikan nilai byte dari setiap karakter dengan angka oktal. Anda dapat membagi transformasi mereka di seluruh rentang, juga.Perintah di atas akan mengubah semua karakter huruf besar menjadi huruf kecil, mengabaikan karakter huruf kecil seluruhnya, dan mengubah semua karakter lain menjadi baris baru. Tentu saja, maka Anda berakhir dengan satu ton garis kosong. The
tr
-s
mengulangi queeze beralih dapat berguna dalam kasus itu, tapi jika Anda menggunakannya di samping[:upper:]
untuk[:lower:]
transformasi maka Anda berakhir meremas karakter huruf besar juga. Dengan cara itu masih membutuhkan filter kedua seperti ......atau...
... Dan akhirnya menjadi jauh lebih nyaman daripada melakukan ...
... yang menekan
-c
omplement karakter alfabet secara berurutan menjadi satu baris baru, kemudian melakukan transformasi atas ke bawah di sisi lain pipa.Itu bukan untuk mengatakan bahwa rentang sifat itu tidak berguna. Hal-hal seperti:
... bisa sangat berguna karena mengubah byte input ke semua digit pada spektrum spread nilai-nilainya. Buang tidak, mau tidak, kau tahu.
Cara lain untuk melakukan transformasi bisa melibatkan
dd
.Karena
dd
dapat melakukan keduanyaunblock
danlcase
konversi pada saat yang sama, bahkan mungkin untuk melewati banyak pekerjaan untuk itu. Tapi itu hanya bisa sangat berguna jika Anda dapat secara akurat memprediksi jumlah byte per kata - atau paling tidak dapat mengimbangi setiap kata dengan spasi sebelumnya ke jumlah byte yang dapat diprediksi, karenaunblock
makan spasi tambahan di akhir setiap blok.sumber
dd
terlibat :)