Pengkodean karakter lokal Anda (yang dapat Anda ketahui locale charmap
) adalah multi-byte per karakter.
Yang paling umum saat ini adalah UTF-8 di mana karakter dapat dikodekan lebih dari 1 hingga 4 byte. Tidak semua urutan byte membentuk karakter yang valid di UTF-8. Setiap karakter non-ASCII dalam UTF-8 mulai dengan satu byte yang memiliki dua bit tertinggi yang ditetapkan dan memberi tahu berapa banyak byte dengan set bit tertinggi (tetapi bukan yang tertinggi kedua) diikuti.
/dev/urandom
berisi aliran byte acak. tr
mentransliterasi karakter, sehingga perlu mendekode byte tersebut sebagai karakter. Semua karakter ASCII dalam jangkauan Anda semua dikodekan pada satu karakter di UTF-8, tetapi tr
masih perlu mendekodekan semua karakter. Misalnya ada pengkodean multi-byte lainnya di mana beberapa karakter selain A
berisi 0x41 byte (kode untuk A
).
Karena aliran byte acak itu pasti mengandung urutan yang tidak valid (misalnya 0x80 byte dengan sendirinya tidak valid dalam UTF-8 karena karakter non-ASCII harus dimulai dengan byte yang lebih besar dari 0xc1 (0xc0 dan 0xc1 tidak ada dalam UTF- 8 karakter)), jadi tr
kembali dengan kesalahan saat itu terjadi.
Apa yang Anda inginkan di sini adalah mempertimbangkan aliran byte sebagai karakter dalam penyandian yang memiliki satu byte per karakter. Apa pun yang Anda pilih tidak penting karena semua karakter dalam rentang Anda (dengan asumsi oleh AZ, yang Anda maksud adalah ABCDEFGHIJKLMNOPQRSTUVWXYZ dan bukan hal-hal seperti Ý
, Ê
) adalah bagian dari rangkaian karakter portabel sehingga dikodekan sama di semua rangkaian karakter yang didukung pada sistem Anda.
Untuk itu, Anda akan menetapkan LC_CTYPE
variabel lokalisasi yang merupakan variabel yang menentukan charset yang digunakan dan hal-hal seperti apa blank
, alpha
kelas karakter berisi. Tetapi untuk definisi rentang AZ, Anda juga ingin mengatur LC_COLLATE
variabel (variabel yang menentukan urutan string).
The C
alias POSIX
lokal adalah salah satu yang jaminan karakter single-byte dan AZ adalah ABCDEFGHIJKLMNOPQRSTUVWXYZ. Anda bisa melakukannya:
LC_CTYPE=C LC_COLLATE=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
(di sini memindahkan -
ke ujung, jika tidak, )-+
akan diambil sebagai rentang seperti A-Z
)
Tetapi perhatikan bahwa LC_ALL
variabel menimpa semua variabel LC_*
dan lainnya LANG
. Jadi, jika LC_ALL
sudah ditentukan, hal di atas tidak akan berpengaruh. Jadi, alih-alih, Anda cukup melakukannya:
LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'
Itu akan memengaruhi hal-hal lain seperti bahasa pesan kesalahan, tetapi bagaimanapun, mengubah LC_CTYPE bisa saja menjadi masalah untuk pesan kesalahan (misalnya, tidak ada cara untuk mengekspresikan pesan kesalahan Rusia atau Jepang di charset dari lokal C).
xargs
...