Bagaimana cara saya mendapatkan nilai ASCII dari alfabet?
Misalnya, 97
untuk a
?
bash
bash-script
ascii
xmpirate
sumber
sumber
"'A"
benar sedangkan jika Anda menggunakan"A"
ia akan berkata:A: invalid number
. Tampaknya itu dilakukan pada sisi printf (yaitu, di shell,"'A"
memang 2 karakter, a'
dan aA
. Mereka dilewatkan ke printf. Dan dalam konteks printf, itu dikonversi ke nilai ascii dari A, (dan akhirnya dicetak sebagai desimal berkat'%d'
. Gunakan'Ox%x'
untuk menunjukkannya dalam heksa atau'0%o'
memilikinya dalam oktal))printf "\\$(printf '%03o' "$1")"
,'%03o'
,LC_CTYPE=C
dan kutipan tunggal di"'$1"
do?Anda dapat melihat seluruh rangkaian dengan:
Anda akan mendapatkan tabel dalam oktal, hex, dan desimal.
sumber
Jika Anda ingin memperluasnya ke karakter UTF-8:
Dengan
bash
,ksh
atauzsh
bawaan:sumber
iceweasel
aktifDebian sid
. Font yang dikonfirmasi oleh konsol web iceweasel adalah "DejaVu Sans" dan saya punya ttf-dejavu ttf-dejavu-core ttf-dejavu-paket tambahan yang diinstal yang berasal dari Debian dengan upstream di dejavu-fonts.orgctbl()
tampaknya benar memungkinkan saya untuk menampilkannya, dan untuk mengiris char dari kepala string denganprintf
, tetapi menempatkan4*((o1=360)>=(d1=240)|(o2=237)>=(d2=159)|(o3=230)>=(d3=152)|(o4=210)>=(d4=136))
di$OPTARG
untuk nilai byte.Ini bekerja dengan baik,
persis sama dengan:
sumber
echo -n
menekan trailing newline menghilangkan kebutuhan untuktr -d "\n"
echo
, tidak dalam gema yang sesuai dengan Unix misalnya.printf %s A
akan menjadi yang portabel.Saya akan mencari solusi Bash yang sederhana (dan elegan?):
Untuk dalam skrip Anda dapat menggunakan yang berikut:
Perhatikan kutipan tunggal sebelum CharValue. Itu wajib ...
sumber
printf "%d"
.Yang pertama
ctbl()
- di atas sana - hanya berjalan satu kali. Ini menghasilkan output berikut (yang telah difiltersed -n l
demi printability) :... yang semuanya 8-bit byte (kurang
NUL
) , dibagi menjadi empat string yang dikutip shell dibagi secara merata pada batas 64-byte. String mungkin diwakili dengan rentang oktal suka\200\1-\77
,\100-\177
,\200-\277
,\300-\377
, di mana byte 128 digunakan sebagai tempat pemegang untukNUL
.Pertama
ctbl()
's seluruh tujuan untuk keberadaan adalah untuk menghasilkan string tersebut sehinggaeval
dapat menentukan keduactbl()
fungsi dengan mereka secara harfiah tertanam setelahnya. Dengan cara itu mereka dapat direferensikan dalam fungsi tanpa perlu membuatnya lagi setiap kali dibutuhkan. Ketikaeval
mendefinisikanctbl()
fungsi kedua , yang pertama akan berhenti.Setengah bagian atas dari
ctbl()
fungsi kedua sebagian besar tambahan di sini - ia dirancang untuk membuat serialisasi portabilitas shell dengan aman saat ini dan apa pun yang mungkin mempengaruhi ketika dipanggil. Loop atas akan mengutip setiap kutipan dalam nilai-nilai variabel apa pun yang mungkin ingin digunakan, dan kemudian menumpuk semua hasil dalam parameter posisinya.Dua baris pertama, bagaimanapun, pertama segera mengembalikan 0 dan diatur
$OPTARG
ke sama jika argumen pertama fungsi tidak mengandung setidaknya satu karakter. Dan jika ya, baris kedua segera memotong argumen pertamanya hanya karakter pertama - karena fungsi hanya menangani karakter pada suatu waktu. Yang penting, ia melakukan ini dalam konteks lokal saat ini, yang berarti bahwa jika karakter dapat terdiri lebih dari satu byte, maka, asalkan shell dengan benar mendukung multi-byte chars, ia tidak akan membuang byte kecuali kecuali yang tidak ada dalam karakter pertama dari argumen pertamanya.Itu kemudian melakukan loop simpan jika diperlukan, dan setelah itu mendefinisikan kembali konteks lokal saat ini ke lokal C untuk setiap kategori dengan menetapkan
LC_ALL
variabel. Dari titik ini, satu karakter hanya dapat terdiri dari satu byte, dan jadi jika ada beberapa byte dalam karakter pertama dari argumen pertama, ini sekarang harus dialamatkan masing-masing sebagai karakter individu dalam hak mereka sendiri.Karena alasan inilah maka bagian kedua dari fungsi adalah
while
loop , sebagai lawan dari urutan berjalan tunggal. Dalam kebanyakan kasus, ia mungkin hanya akan mengeksekusi satu kali per panggilan, tetapi, jika shell yangctbl()
didefinisikan dengan benar menangani karakter multi-byte, itu mungkin loop.Perhatikan bahwa
$(ctbl)
substitusi perintah di atas hanya pernah dievaluasi sekali - padaeval
saat fungsi awalnya didefinisikan - dan bahwa selamanya setelah itu token diganti dengan output literal dari substitusi perintah yang disimpan ke dalam memori shell. Hal yang sama berlaku untuk duacase
pergantian perintah pola. Fungsi ini tidak pernah memanggil subkulit atau perintah lainnya. Ini juga tidak akan pernah mencoba untuk membaca atau menulis input / output (kecuali dalam kasus beberapa pesan diagnostik shell - yang mungkin menunjukkan bug) .Perhatikan juga bahwa tes untuk kontinuitas loop tidak hanya
[ -n "$a" ]
, karena, seperti yang saya temukan pada frustasi saya, untuk beberapa alasanbash
shell tidak:... dan jadi saya secara eksplisit membandingkan
$a
len ke 0 untuk setiap iterasi, yang, juga tidak dapat dijelaskan, berperilaku berbeda (baca: dengan benar) .The
case
cek byte pertama untuk dimasukkan dalam salah satu dari empat senar dan toko referensi ke set byte dalam$b
. Setelah itu, empat parameter posisi pertama shell adalahset
string yang disematkaneval
dan ditulis olehctbl()
pendahulunya.Selanjutnya, apa pun yang tersisa dari argumen pertama sekali lagi terpotong sementara untuk karakter pertamanya - yang sekarang harus dipastikan sebagai byte tunggal. Byte pertama ini digunakan sebagai referensi untuk melepas dari ujung string yang cocok dan referensi di
$b
adalaheval
untuk mewakili parameter posisi sehingga segala sesuatu dari byte referensi ke byte terakhir dalam string dapat diganti. Tiga string lainnya dijatuhkan sepenuhnya dari parameter posisi.Pada titik ini nilai byte (modulo 64) dapat dirujuk sebagai len string:
Sedikit matematika kemudian dilakukan untuk mendamaikan modulus berdasarkan nilai dalam
$b
, byte pertama in$a
secara permanen dihapus, dan output untuk siklus saat ini ditambahkan ke tumpukan sambil menunggu penyelesaian sebelum loop daur ulang untuk memeriksa apakah$a
benar-benar kosong.Ketika
$a
benar-benar kosong, semua nama dan negara - dengan pengecualian$OPTARG
- bahwa fungsi yang terpengaruh selama pelaksanaannya dikembalikan ke keadaan sebelumnya - apakah disetel dan bukan nol, setel dan batal, atau tidak disetel - dan hasilnya disimpan untuk$OPTARG
sebagai fungsi kembali. Nilai pengembalian aktual adalah satu kurang dari jumlah total byte dalam karakter pertama dari argumen pertamanya - sehingga setiap karakter byte tunggal mengembalikan nol dan karakter multi-byte akan mengembalikan lebih dari nol - dan format outputnya sedikit aneh.Nilai
ctbl()
menghemat untuk$OPTARG
adalah shell ekspresi aritmatika valid yang, jika dievaluasi, bersamaan akan mengatur nama variabel bentuk$o1
,$d1
,$o2
,$d2
untuk desimal dan nilai-nilai oktal dari semua byte masing-masing dalam karakter pertama dari argumen pertama, tapi akhirnya mengevaluasi total jumlah byte dalam argumen pertamanya. Saya memiliki jenis alur kerja tertentu dalam pikiran ketika menulis ini, dan saya pikir mungkin demonstrasi dalam rangka.Saya sering menemukan alasan untuk memisahkan string dengan
getopts
seperti:Saya mungkin melakukan sedikit lebih dari sekedar mencetaknya char per baris, tapi semuanya mungkin. Dalam hal apapun, saya belum menemukan
getopts
yang benar akan melakukan (strike itu -dash
'sgetopts
melakukannya char by char, tapibash
pasti tidak) :Baik. Jadi saya mencoba ...
Alur kerja semacam itu - byte untuk byte / char untuk jenis char - adalah salah satu yang sering saya bahas ketika melakukan hal-hal tty. Di ujung depan input, Anda perlu mengetahui nilai char segera setelah Anda membacanya, dan Anda perlu ukurannya (terutama ketika menghitung kolom) , dan Anda perlu karakter untuk menjadi karakter keseluruhan .
Dan sekarang saya punya
ctbl()
:Catatan yang
ctbl()
tidak benar-benar mendefinisikan$[od][12...]
variabel - tidak pernah memiliki efek abadi pada keadaan apa pun tetapi$OPTARG
- tetapi hanya menempatkan string$OPTARG
yang dapat digunakan untuk mendefinisikan mereka - yang adalah bagaimana saya mendapatkan salinan kedua dari masing-masing karakter di atas dengan melakukanprintf "\\$o1\\$o2"
karena mereka diset setiap kali saya mengevaluasi$(($OPTARG))
. Tapi di mana saya melakukannya saya juga mendeklarasikan panjang lapangan pengubah untukprintf
's%s
Format argumen string, dan karena ekspresi selalu mengevaluasi dengan jumlah total byte dalam karakter, saya mendapatkan seluruh karakter pada output ketika saya lakukan:sumber
[ "$(printf \\1)" ]|| ! echo but its not null!
sementara itu, merasa bebas untuk lebih mengenal diri sendiri dengan praktik komentar yang bermakna, kecuali jika Anda merekomendasikan kontes yang sebenarnya ...?sh
bahasa perintah POSIX .bash
adalah bourne lagi supraset yang sama, dan sebagian besar motivator yang terjal untuk banyak perawatan yang diberikan di atas menuju ukuran karakter yang luas portabel, memperluas diri dan namespace jenis apa pun.bash
harus menangani sebagian besar dari ini, tetapic
bahasaprintf
itu, dan mungkin, kekurangan kemampuan di atas disediakan.Bukan skrip shell, tetapi berfungsi
Output sampel
sumber
konsole
xxd<press enter>
<SHIFT+INSERT><CTRL+D>
Anda mendapatkan sesuatu seperti:
Anda tahu simbol yang Anda tempel memiliki kode hex
0xfb
sumber