اگر شما یک مقدار معین هگزادسیمال یا اُکتال دارید(در زمان نوشتن اسکریپت)، دقیقاً میتوانید printf را به کار ببرید:
# POSIX printf '\x27\047\n'
این کُد دو کاراکتر لفظی
ExpandedString=$'\x27\047\u0027\U00000027\n' echo -n "$ExpandedString"
یک رویکرد دیگر، رشتههای $'...' قبل از ارزیابی ، [در متغیری]پوشش داده میشوند و میتوانند به طور مستقیم در کُد تعبیه شوند.
اگر احتیاج دارید کاراکترها(یا مقادیر عددی کاراکتر اسکی) که از قبل شناخته شده نیستند(به عنوان مثال در متغیرها) را تبدیل کنید، میتوانید ازکُد کمی پیچیدهتر استفاده کنید:
# POSIX # chr() - مقدار دسیمال را به کاراکتر اسکی نمایندهاش تبدیل میکند # ord() - کاراکتر اسکی را به مقدار دسیمال آن تبدیل میکند chr() { [ ${1} -lt 256 ] || return 1 printf \\$(printf '%03o' $1) } # یک نگارش دیگر با تبدیل به اُکتال با استفاده از محاسبه # سریعتر به علت آنکه از پوسته فرعی اجتناب میکند chr () { [ ${1} -lt 256 ] || return 1 printf \\$(($1/64*100+$1%64/8*10+$1%8)) } # نگارش دیگر با استفاده از متغیر موقت برای اجتناب از پوسته فرعی # نیاز دارد bash 3.1 این روش به chr() { local tmp [ ${1} -lt 256 ] || return 1 printf -v tmp '%03o' "$1" printf \\"$tmp" } ord() { LC_CTYPE=C printf '%d' "'$1" } # hex() - کاراکتر اسکی را به مقدار هگزادسیمال تبدیل میکند # unhex() - مقدار هگزادسیمال را به کاراکتر اسکی تبدیل میکند hex() { LC_CTYPE=C printf '%x' "'$1" } unhex() { printf \\x"$1" } # :مثالها chr $(ord A) # ==> A ord $(chr 65) # ==> 65
تابع ord بالا کاملاًماهرانه است.
ماهرانه؟ نسبتاً، این تابع از یک ویژگی استفاده میکند که من مستند شده آن را درجایی نمی توانم پیدا کنم --گذاشتن یک نقلقول منفرد در جلوی یک عدد صحیح. تأثیر شسته رُفته، اما در این دنیای فانی چطور آن را کشف کردید؟ شیرجه رفتن در کُد منبع؟ -- GreyCat
مثال پایین اخیراً کاملاً پذیرفته شد و لازم است پاکیزه و تأیید اعتبار بشود.
برای مقادیر 0x80 - 0xff ناسازگاری بین UTF-8 و ExtAscii
مقدار |
EAscii |
UTF-8 |
UTF-16 |
UTF-32 |
0x20 |
"\x20" |
"\x20" |
\u0020 |
\U00000020 |
0x20 |
"\x7f" |
"\x7f" |
\u007f |
\U0000007f |
0x80 |
"\x80" |
"\xc2\x80" |
\u0080 |
\U00000080 |
0xff |
"\xff" |
"\xc3\xbf" |
\u00ff |
\U000000ff |
0x100 |
N/A |
"\xc4\x80" |
\u0100 |
\U00000100 |
0x1000 |
N/A |
"\xc8\x80" |
\u1000 |
\U00001000 |
0xffff |
N/A |
"\xef\xbf\xbf" |
\uffff |
\U0000ffff |
0x10000 |
N/A |
"\xf0\x90\x80\x80" |
\ud800\udc00 |
\U00010000 |
0xfffff |
N/A |
"\xf3\xbf\xbf\xbf" |
\udbbf\udfff |
\U000fffff |
0x10000000 |
N/A |
"\xfc\x90\x80\x80\x80\x80" |
N/A |
\U10000000 |
0x7fffffff |
N/A |
"\xfd\xbf\xbf\xbf\xbf\xbf" |
N/A |
\U7fffffff |
0x80000000 |
N/A |
N/A |
N/A |
N/A |
0xffffffff |
N/A |
N/A |
N/A |
N/A |
########################################################################### ## برای تبدیل کاراکتر به عدد ord خانواده ########################################################################### # ord < نام متغیر بازگشتی > < کاراکتر > [رشته قالبندی اختیاری] # ord_hex < نام متغیر بازگشتی > < کاراکتر > # ord_oct < نام متغیر بازگشتی > < کاراکتر > # ord_utf8 < نام متغیر بازگشتی > < کاراکتر > [رشته قالبندی اختیاری] # ord_eascii < نام متغیر بازگشتی > < کاراکتر > [رشته قالبندی اختیاری] # ord_echo < کاراکتر > [رشته قالبندی اختیاری] # ord_hex_echo < کاراکتر > # ord_oct_echo < کاراکتر > # ord_utf8_echo < کاراکتر > [رشته قالبندی اختیاری] # ord_eascii_echo < کاراکتر > [رشته قالبندی اختیاری] # # : توضیحات # محلی را تبدیل میکند و مقدار encoding کاراکتر به کار رفته با # آن را در متغیر تعیین شده ذخیره میکند # # ord # ord_hex خروجی به هگزا # ord_oct خروجی اُکتال # ord_utf8 UTF8 اجباری decoding # ord_eascii اجباری دسیمال decoding # ord_echo چاپ در خروجی استاندارد function ord { printf -v "${1?Missing Dest Variable}" "${3:-%d}" "'${2?Missing Char}" } function ord_oct { ord "${@:1:2}" "0%o" } function ord_hex { ord "${@:1:2}" "0x%x" } function ord_utf8 { LC_CTYPE=C.UTF-8 ord "${@}" } function ord_eascii { LC_CTYPE=C ord "${@}" } function ord_echo { printf "${2:-%d}" "'${1?Missing Char}" } function ord_oct_echo { ord_echo "${1}" "0%o" } function ord_hex_echo { ord_echo "${1}" "0x%x" } function ord_utf8_echo { LC_CTYPE=C.UTF-8 ord_echo "${@}" } function ord_eascii_echo { LC_CTYPE=C ord_echo "${@}" } ########################################################################### ## برای تبدیل عدد به کاراکتر chr خانواده ########################################################################### # chr_utf8 < نام متغیر بازگشتی > < عدد صحیح برای تبدیل > # chr_eascii < نام متغیر بازگشتی > < عدد صحیح برای تبدیل > # chr < نام متغیر بازگشتی > < عدد صحیح برای تبدیل > # chr_oct < نام متغیر بازگشتی > < عدد اُکتال برای تبدیل > # chr_hex < نام متغیر بازگشتی > < عدد هگزا برای تبدیل > # chr_utf8_echo < عدد صحیح برای تبدیل > # chr_eascii_echo < عدد صحیح برای تبدیل > # chr_echo < عدد صحیح برای تبدیل > # chr_oct_echo < عدد اُکتال برای تبدیل > # chr_hex_echo < عدد هگزا برای تبدیل > # # : توضیحات # مقدار دسیمال را به کاراکتری که آن را نمایندگی # میکند تبدیل و متغیر تعیین شده ذخیره میکند # # chr سعی میکند قالب خروجی را حدس بزند # chr_utf8 UTF8 اجباری encoding # chr_eascii eascii اجباری encoding # chr_echo چاپ در خروجی استاندارد # function chr_utf8_m { local val # # پشتیبانی میکند \u \U از 4.2 فقط از نگارش bash # # این یک مثال از چگونگی کُد گذاری به طور دستی است # استفاده میکند کار خواهد کرد -v که از Bash 3.1 از نگارش # if [[ ${2:?Missing Ordinal Value} -le 0x7f ]]; then printf -v val "\\%03o" "${2}" elif [[ ${2} -le 0x7ff ]]; then printf -v val "\\%03o\\%03o" \ $(( (${2}>> 6) |0xc0 )) \ $(( ( ${2} &0x3f)|0x80 )) elif [[ ${2} -le 0xffff ]]; then printf -v val "\\%03o\\%03o\\%03o" \ $(( ( ${2}>>12) |0xe0 )) \ $(( ((${2}>> 6)&0x3f)|0x80 )) \ $(( ( ${2} &0x3f)|0x80 )) elif [[ ${2} -le 0x1fffff ]]; then printf -v val "\\%03o\\%03o\\%03o\\%03o" \ $(( ( ${2}>>18) |0xf0 )) \ $(( ((${2}>>12)&0x3f)|0x80 )) \ $(( ((${2}>> 6)&0x3f)|0x80 )) \ $(( ( ${2} &0x3f)|0x80 )) elif [[ ${2} -le 0x3ffffff ]]; then printf -v val "\\%03o\\%03o\\%03o\\%03o\\%03o" \ $(( ( ${2}>>24) |0xf8 )) \ $(( ((${2}>>18)&0x3f)|0x80 )) \ $(( ((${2}>>12)&0x3f)|0x80 )) \ $(( ((${2}>> 6)&0x3f)|0x80 )) \ $(( ( ${2} &0x3f)|0x80 )) elif [[ ${2} -le 0x7fffffff ]]; then printf -v val "\\%03o\\%03o\\%03o\\%03o\\%03o\\%03o" \ $(( ( ${2}>>30) |0xfc )) \ $(( ((${2}>>24)&0x3f)|0x80 )) \ $(( ((${2}>>18)&0x3f)|0x80 )) \ $(( ((${2}>>12)&0x3f)|0x80 )) \ $(( ((${2}>> 6)&0x3f)|0x80 )) \ $(( ( ${2} &0x3f)|0x80 )) else printf -v "${1:?Missing Dest Variable}" "" return 1 fi printf -v "${1:?Missing Dest Variable}" "${val}" } function chr_utf8 { local val [[ ${2?Missing Ordinal Value} -lt 0x80000000 ]] || return 1 if [[ ${2} -lt 0x100 && ${2} -ge 0x80 ]]; then # bash 4.2 incorrectly encodes # \U000000ff as \xff so encode manually printf -v val "\\%03o\%03o" $(( (${2}>>6)|0xc0 )) $(( (${2}&0x3f)|0x80 )) else printf -v val '\\U%08x' "${2}" fi printf -v ${1?Missing Dest Variable} ${val} } function chr_eascii { local val # کوچکتر است 0x100 کسب اطمینان که کمیت از # در غیر این صورت به این شکل تمام میکنیم # \xVVNNNNN # میباشد \xVV = char یک رشته عددی و NNNNN که در آن # chr "0x44321" => "D321" به طوری که [[ ${2?Missing Ordinal Value} -lt 0x100 ]] || return 1 printf -v val '\\x%02x' "${2}" printf -v ${1?Missing Dest Variable} ${val} } function chr { if [ "${LC_CTYPE:-${LC_ALL:-}}" = "C" ]; then chr_eascii "${@}" else chr_utf8 "${@}" fi } function chr_dec { # صفرهای مقدم از بین میروند در غیر آن صورت # به عنوان اُکتا تفسیر میشوند chr "${1}" "${2#${2%%[!0]*}}" } function chr_oct { chr "${1}" "0${2}" } function chr_hex { chr "${1}" "0x${2#0x}" } function chr_utf8_echo { local val [[ ${1?Missing Ordinal Value} -lt 0x80000000 ]] || return 1 if [[ ${1} -lt 0x100 && ${1} -ge 0x80 ]]; then # bash 4.2 incorrectly encodes # \U000000ff as \xff so encode manually printf -v val '\\%03o\\%03o' $(( (${1}>>6)|0xc0 )) $(( (${1}&0x3f)|0x80 )) else printf -v val '\\U%08x' "${1}" fi printf "${val}" } function chr_eascii_echo { local val # کوچکتر است 0x100 کسب اطمینان که کمیت از # در غیر این صورت به این شکل تمام میکنیم # \xVVNNNNN # میباشد \xVV = char یک رشته عددی و NNNNN که در آن # chr "0x44321" => "D321" به طوری که [[ ${1?Missing Ordinal Value} -lt 0x100 ]] || return 1 printf -v val '\\x%x' "${1}" printf "${val}" } function chr_echo { if [ "${LC_CTYPE:-${LC_ALL:-}}" = "C" ]; then chr_eascii_echo "${@}" else chr_utf8_echo "${@}" fi } function chr_dec_echo { # صفرهای مقدم از بین میروند در غیر آن صورت # به عنوان اُکتا تفسیر میشوند chr_echo "${1#${1%%[!0]*}}" } function chr_oct_echo { chr_echo "0${1}" } function chr_hex_echo { chr_echo "0x${1#0x}" } # # کُد ساده معتبرسازی # function test_echo_func { local Outcome _result _result="$( "${1}" "${2}" )" [ "${_result}" = "${3}" ] && Outcome="Pass" || Outcome="Fail" printf "# %-20s %-6s => " "${1}" "${2}" "${_result}" "${3}" printf "[ "%16q" = "%-16q"%-5s ] " "${_result}" "${3}" "(${3//[[:cntrl:]]/_})" printf "%s\n" "${Outcome}" } function test_value_func { local Outcome _result "${1}" _result "${2}" [ "${_result}" = "${3}" ] && Outcome="Pass" || Outcome="Fail" printf "# %-20s %-6s => " "${1}" "${2}" "${_result}" "${3}" printf "[ "%16q" = "%-16q"%-5s ] " "${_result}" "${3}" "(${3//[[:cntrl:]]/_})" printf "%s\n" "${Outcome}" } test_echo_func chr_echo "$(ord_echo "A")" "A" test_echo_func ord_echo "$(chr_echo "65")" "65" test_echo_func chr_echo "$(ord_echo "ö")" "ö" test_value_func chr "$(ord_echo "A")" "A" test_value_func ord "$(chr_echo "65")" "65" test_value_func chr "$(ord_echo "ö")" "ö" # chr_echo 65 => [ A = A (A) ] Pass # ord_echo A => [ 65 = 65 (65) ] Pass # chr_echo 246 => [ $'\303\266' = $'\303\266' (ö) ] Pass # chr 65 => [ A = A (A) ] Pass # ord A => [ 65 = 65 (65) ] Pass # chr 246 => [ $'\303\266' = $'\303\266' (ö) ] Pass # test_echo_func chr_echo "65" A test_echo_func chr_echo "065" 5 test_echo_func chr_dec_echo "065" A test_echo_func chr_oct_echo "65" 5 test_echo_func chr_hex_echo "65" e test_value_func chr "65" A test_value_func chr "065" 5 test_value_func chr_dec "065" A test_value_func chr_oct "65" 5 test_value_func chr_hex "65" e # chr_echo 65 => [ A = A (A) ] Pass # chr_echo 065 => [ 5 = 5 (5) ] Pass # chr_dec_echo 065 => [ A = A (A) ] Pass # chr_oct_echo 65 => [ 5 = 5 (5) ] Pass # chr_hex_echo 65 => [ e = e (e) ] Pass # chr 65 => [ A = A (A) ] Pass # chr 065 => [ 5 = 5 (5) ] Pass # chr_dec 065 => [ A = A (A) ] Pass # chr_oct 65 => [ 5 = 5 (5) ] Pass # chr_hex 65 => [ e = e (e) ] Pass #test_value_func chr 0xff $'\xff' test_value_func chr_eascii 0xff $'\xff' test_value_func chr_utf8 0xff $'\uff' # به طور صحیح آن را رمزگشایی نمیکند bash مورد بالا ناموفق است چون test_value_func chr_utf8 0xff $'\303\277' test_value_func chr_utf8 0x100 $'\u100' test_value_func chr_utf8 0x1000 $'\u1000' test_value_func chr_utf8 0xffff $'\uffff' # chr_eascii 0xff => [ $'\377' = $'\377' (�) ] Pass # chr_utf8 0xff => [ $'\303\277' = $'\377' (�) ] Fail # chr_utf8 0xff => [ $'\303\277' = $'\303\277' (ÿ) ] Pass # chr_utf8 0x100 => [ $'\304\200' = $'\304\200' (Ā) ] Pass # chr_utf8 0x1000 => [ $'\341\200\200' = $'\341\200\200' (က) ] Pass # chr_utf8 0xffff => [ $'\357\277\277' = $'\357\277\277' (���) ] Pass test_value_func ord_utf8 "A" 65 test_value_func ord_utf8 "ä" 228 test_value_func ord_utf8 $'\303\277' 255 test_value_func ord_utf8 $'\u100' 256 ######################################################### # برای مساعدت در اشکالزدایی این کد را امتحان کنید ######################################################### printf "%q\n" $'\xff' # => $'\377' printf "%q\n" $'\uffff' # => $'\357\277\277' printf "%q\n" "$(chr_utf8_echo 0x100)" # => $'\304\200' # # موقعی که تشخیص مشکلات لازم میشود این کد بسیار کمک میکند # xterm و(یا) برنامه read با # من در وقوع خطا زیاد از این کد برای ایجاد پیغام خطای قابل خواندن استفاده میکنم # به عنوان مثال echo "Enter type to test, Enter to continue" while read -srN1 ; do ord asciiValue "${REPLY}" case "${asciiValue}" in 10) echo "Goodbye" ; break ;; 20|21|22) echo "Yay expected input" ;; *) printf ':( Unexpected Input 0x%02x %q "%s"\n' "${asciiValue}" "${REPLY}" "${REPLY//[[:cntrl:]]}" ;; esac done ######################################################### # 1 رویکرد عجیب و غریبتر ######################################################### # باید از این استفاده میکردم LC_CTYPE=C من قبل از کشف رویکرد # printf "EAsciiLookup=%q" "$(for (( x=0x0; x<0x100 ; x++)); do printf '%b' $(printf '\\x%02x' "$x"); done)" EAsciiLookup=$'\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023' EAsciiLookup+=$'\024\025\026\027\030\031\032\E\034\035\036\037 !"#$%&\'()*+,-' EAsciiLookup+=$'./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghi' EAsciiLookup+=$'jklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210' EAsciiLookup+=$'\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227' EAsciiLookup+=$'\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246' EAsciiLookup+=$'\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265' EAsciiLookup+=$'\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304' EAsciiLookup+=$'\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323' EAsciiLookup+=$'\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342' EAsciiLookup+=$'\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361' EAsciiLookup+=$'\362\363\364\365\366\367\370\371\372\373\374\375\376\377' function ord_eascii2 { local idx="${EAsciiLookup%%${2:0:1}*}" eval ${1}'=$(( ${#idx} +1 ))' } ######################################################### # 2 رویکرد عجیب و غریبتر ######################################################### #printf "EAsciiLookup2=(\n %s\n)" "$(for (( x=0x1; x<0x100 ; x++)); do printf '%-18s' "$(printf '[_%q]="0x%02x"' "$(printf "%b" "$(printf '\\x%02x' "$x")")" $x )" ; [ "$(($x%6))" != "0" ] || echo -en "\n " ; done)" typeset -A EAsciiLookup2 EAsciiLookup2=( [_$'\001']="0x01" [_$'\002']="0x02" [_$'\003']="0x03" [_$'\004']="0x04" [_$'\005']="0x05" [_$'\006']="0x06" [_$'\a']="0x07" [_$'\b']="0x08" [_$'\t']="0x09" [_'']="0x0a" [_$'\v']="0x0b" [_$'\f']="0x0c" [_$'\r']="0x0d" [_$'\016']="0x0e" [_$'\017']="0x0f" [_$'\020']="0x10" [_$'\021']="0x11" [_$'\022']="0x12" [_$'\023']="0x13" [_$'\024']="0x14" [_$'\025']="0x15" [_$'\026']="0x16" [_$'\027']="0x17" [_$'\030']="0x18" [_$'\031']="0x19" [_$'\032']="0x1a" [_$'\E']="0x1b" [_$'\034']="0x1c" [_$'\035']="0x1d" [_$'\036']="0x1e" [_$'\037']="0x1f" [_\ ]="0x20" [_\!]="0x21" [_\"]="0x22" [_\#]="0x23" [_\$]="0x24" [_%]="0x25" [_\&]="0x26" [_\']="0x27" [_\(]="0x28" [_\)]="0x29" [_\*]="0x2a" [_+]="0x2b" [_\,]="0x2c" [_-]="0x2d" [_.]="0x2e" [_/]="0x2f" [_0]="0x30" [_1]="0x31" [_2]="0x32" [_3]="0x33" [_4]="0x34" [_5]="0x35" [_6]="0x36" [_7]="0x37" [_8]="0x38" [_9]="0x39" [_:]="0x3a" [_\;]="0x3b" [_\<]="0x3c" [_=]="0x3d" [_\>]="0x3e" [_\?]="0x3f" [_@]="0x40" [_A]="0x41" [_B]="0x42" [_C]="0x43" [_D]="0x44" [_E]="0x45" [_F]="0x46" [_G]="0x47" [_H]="0x48" [_I]="0x49" [_J]="0x4a" [_K]="0x4b" [_L]="0x4c" [_M]="0x4d" [_N]="0x4e" [_O]="0x4f" [_P]="0x50" [_Q]="0x51" [_R]="0x52" [_S]="0x53" [_T]="0x54" [_U]="0x55" [_V]="0x56" [_W]="0x57" [_X]="0x58" [_Y]="0x59" [_Z]="0x5a" [_\[]="0x5b" #[_\\]="0x5c" #[_\]]="0x5d" [_\^]="0x5e" [__]="0x5f" [_\`]="0x60" [_a]="0x61" [_b]="0x62" [_c]="0x63" [_d]="0x64" [_e]="0x65" [_f]="0x66" [_g]="0x67" [_h]="0x68" [_i]="0x69" [_j]="0x6a" [_k]="0x6b" [_l]="0x6c" [_m]="0x6d" [_n]="0x6e" [_o]="0x6f" [_p]="0x70" [_q]="0x71" [_r]="0x72" [_s]="0x73" [_t]="0x74" [_u]="0x75" [_v]="0x76" [_w]="0x77" [_x]="0x78" [_y]="0x79" [_z]="0x7a" [_\{]="0x7b" [_\|]="0x7c" [_\}]="0x7d" [_~]="0x7e" [_$'\177']="0x7f" [_$'\200']="0x80" [_$'\201']="0x81" [_$'\202']="0x82" [_$'\203']="0x83" [_$'\204']="0x84" [_$'\205']="0x85" [_$'\206']="0x86" [_$'\207']="0x87" [_$'\210']="0x88" [_$'\211']="0x89" [_$'\212']="0x8a" [_$'\213']="0x8b" [_$'\214']="0x8c" [_$'\215']="0x8d" [_$'\216']="0x8e" [_$'\217']="0x8f" [_$'\220']="0x90" [_$'\221']="0x91" [_$'\222']="0x92" [_$'\223']="0x93" [_$'\224']="0x94" [_$'\225']="0x95" [_$'\226']="0x96" [_$'\227']="0x97" [_$'\230']="0x98" [_$'\231']="0x99" [_$'\232']="0x9a" [_$'\233']="0x9b" [_$'\234']="0x9c" [_$'\235']="0x9d" [_$'\236']="0x9e" [_$'\237']="0x9f" [_$'\240']="0xa0" [_$'\241']="0xa1" [_$'\242']="0xa2" [_$'\243']="0xa3" [_$'\244']="0xa4" [_$'\245']="0xa5" [_$'\246']="0xa6" [_$'\247']="0xa7" [_$'\250']="0xa8" [_$'\251']="0xa9" [_$'\252']="0xaa" [_$'\253']="0xab" [_$'\254']="0xac" [_$'\255']="0xad" [_$'\256']="0xae" [_$'\257']="0xaf" [_$'\260']="0xb0" [_$'\261']="0xb1" [_$'\262']="0xb2" [_$'\263']="0xb3" [_$'\264']="0xb4" [_$'\265']="0xb5" [_$'\266']="0xb6" [_$'\267']="0xb7" [_$'\270']="0xb8" [_$'\271']="0xb9" [_$'\272']="0xba" [_$'\273']="0xbb" [_$'\274']="0xbc" [_$'\275']="0xbd" [_$'\276']="0xbe" [_$'\277']="0xbf" [_$'\300']="0xc0" [_$'\301']="0xc1" [_$'\302']="0xc2" [_$'\303']="0xc3" [_$'\304']="0xc4" [_$'\305']="0xc5" [_$'\306']="0xc6" [_$'\307']="0xc7" [_$'\310']="0xc8" [_$'\311']="0xc9" [_$'\312']="0xca" [_$'\313']="0xcb" [_$'\314']="0xcc" [_$'\315']="0xcd" [_$'\316']="0xce" [_$'\317']="0xcf" [_$'\320']="0xd0" [_$'\321']="0xd1" [_$'\322']="0xd2" [_$'\323']="0xd3" [_$'\324']="0xd4" [_$'\325']="0xd5" [_$'\326']="0xd6" [_$'\327']="0xd7" [_$'\330']="0xd8" [_$'\331']="0xd9" [_$'\332']="0xda" [_$'\333']="0xdb" [_$'\334']="0xdc" [_$'\335']="0xdd" [_$'\336']="0xde" [_$'\337']="0xdf" [_$'\340']="0xe0" [_$'\341']="0xe1" [_$'\342']="0xe2" [_$'\343']="0xe3" [_$'\344']="0xe4" [_$'\345']="0xe5" [_$'\346']="0xe6" [_$'\347']="0xe7" [_$'\350']="0xe8" [_$'\351']="0xe9" [_$'\352']="0xea" [_$'\353']="0xeb" [_$'\354']="0xec" [_$'\355']="0xed" [_$'\356']="0xee" [_$'\357']="0xef" [_$'\360']="0xf0" [_$'\361']="0xf1" [_$'\362']="0xf2" [_$'\363']="0xf3" [_$'\364']="0xf4" [_$'\365']="0xf5" [_$'\366']="0xf6" [_$'\367']="0xf7" [_$'\370']="0xf8" [_$'\371']="0xf9" [_$'\372']="0xfa" [_$'\373']="0xfb" [_$'\374']="0xfc" [_$'\375']="0xfd" [_$'\376']="0xfe" [_$'\377']="0xff" ) function ord_eascii3 { local -i val="${EAsciiLookup2["_${2:0:1}"]-}" if [ "${val}" -eq 0 ]; then case "${2:0:1}" in ]) val=0x5d ;; \\) val=0x5c ;; esac fi eval "${1}"'="${val}"' } # برای تفنن موارد زیر را بررسی کنید time for (( i=0 ; i <1000; i++ )); do ord TmpVar 'a'; done # real 0m0.065s # user 0m0.048s # sys 0m0.000s time for (( i=0 ; i <1000; i++ )); do ord_eascii TmpVar 'a'; done # real 0m0.239s # user 0m0.188s # sys 0m0.000s time for (( i=0 ; i <1000; i++ )); do ord_utf8 TmpVar 'a'; done # real 0m0.225s # user 0m0.180s # sys 0m0.000s time for (( i=0 ; i <1000; i++ )); do ord_eascii2 TmpVar 'a'; done # real 0m1.507s # user 0m1.056s # sys 0m0.012s time for (( i=0 ; i <1000; i++ )); do ord_eascii3 TmpVar 'a'; done # real 0m0.147s # user 0m0.120s # sys 0m0.000s time for (( i=0 ; i <1000; i++ )); do ord_echo 'a' >/dev/null ; done # real 0m0.065s # user 0m0.044s # sys 0m0.016s time for (( i=0 ; i <1000; i++ )); do ord_eascii_echo 'a' >/dev/null ; done # real 0m0.089s # user 0m0.068s # sys 0m0.008s time for (( i=0 ; i <1000; i++ )); do ord_utf8_echo 'a' >/dev/null ; done # real 0m0.226s # user 0m0.172s # sys 0m0.012s
پرسش و پاسخ 71 (آخرین ویرایش 2012-03-14 06:44:55 توسط rgnb-4d0d6130)
تنها روش سالم مدیریت مقادیر زمان در داخل یک برنامه، تبدیل آنها به مقیاس خطی است. شما نمیتوانید "January 17, 2005 at 5:37 PM" را در متغیری ذخیره کنید و انتظار انجام کاری را با آن داشته باشید....
بنابراین، هر برنامه کارآمد از نشانههای زمان با معانی از قبیل «تعداد ثانیههای از نقطه X» استفاده میکند . اینها را نشانهها زمان epoch مینامند. اگر epoch نیمه شب اول ژانویه 1970 بر اساس UTC زیرنویس 1 باشد، آنوقت "Unix timestamp" نیز نامیده میشود، زیرا این روشی است که یونیکس تمام زمانها(ازقبیل زمان ویرایش فایل) را ذخیره میکند.
یونیکس استاندارد، متأسفانه ابزاری برای کار کردن با نشانههای زمان یونیکس ندارد. فرمان date گنو و اخیراً BSD، دارای یک الحاقیه %s برای تولید خروجی در قالب نشانه زمان یونیکس میباشند:
# GNU/BSD date date +%s # 1358612347 زمان فعلی را با قالب یونیکس چاپ میکند به عنوان مثال
موقعی که نیاز به فاصله زمانی بین دو رویداد باشد، این گزینه به طور رایج در اسکریپتها به کار میرود:
# POSIX shell, with GNU/BSD date start=$(date +%s) ... end=$(date +%s) echo "Operation took $(($end - $start)) seconds."
حال، برای تبدیل آن نشانههای زمان یونیکس به مقادیر قابل خواندن انسانی، استفاده از یک برنامه خارجی لازم است. یک شیوه، به کار بردن ترفندی با استفاده از date گنو است:
# GNU date date -d "1970-01-01 UTC + 1358612347 seconds" # .را نسبت به وقت محلی تهران چاپ میکند Sat Jan 19 19:49:07 IRST 2013.
خواندن info date بخش (GNU coreutils:Date input formats) روشن میکند که این فرمان نشانههای زمانِ یونیکسِ پیشوند شده با '@' را میپذیرد، اینطور:
# recent GNU date $ date -d "@1164128484" # .را نسبت به وقت منطقه اروپای مرکزی چاپ میکند "Tue Nov 21 18:01:24 CET 2006"
به هر حال، این ویژگی فقط با نگارشهای جدیدتر date گنو کار میکند -- coreutils 5.3.0 و بالاتر.
اگر شما date گنو را در دسترس ندارید، میتوانید از پرل استفاده کنید:
perl -le "print scalar localtime 1358612347" # را چاپ میکند Sat Jan 19 19:49:07 2013
من در این مثالها نقلقول دوگانه را به کار بردم به طوری که زمان ثابت میتوانست با یک متغیر مرجع تعویض گردد. برای اطلاعات بیشتر در خصوص تغییر قالب خروجی، مستندات date(1) و پرل را ببینید.
نگارشهای جدیدتر Tcl (همچون 8.5) پشتیبانی مناسبی از توابع تاریخ و ساعت دارند. صفحه man tclsh را برای جزئیات نحوه کاربرد آن ملاحظه نمایید. برای مثال:
echo 'puts [clock format [clock scan "today"]]' | tclsh # (تنظیم شودclock format تاریخ امروز را چاپ میکند(قالب میتواند با پارامترها در echo 'puts [clock format [clock scan "fortnight"]]' | tclsh # .تاریخ دو هفته قبل را چاپ میکند echo 'puts [clock format [clock scan "5 years + 6 months ago"]]' | tclsh # ۵/۵ سال قبل با احتساب سال کبیسه و زمان روشنایی روز
یک روش مناسب برای محاسبه ثانیههای سپری شده از 'YYYY MM DD HH MM SS' استفاده از awk میباشد.
echo "2008 02 27 18 50 23" | awk '{print systime() - mktime($0)}' # استفاده میکند epoch برای باز گرداندن زمان فعلی در شکل systime() این کُد از # آن اجرا میکند epoch را روی رشته ورودی برای به دست آوردن زمان mktime() سپس
برای آنکه خواندن آن توسط انسان خواناتر گردد، میتوان از awk گنو (gawk) استفاده نمود: قالببندی رشته در آن مشابه با date است، و به طور دقیق در توابع زمان در gawk نشان داده شده است
echo "YYYY MM DD HH MM SS" | gawk '{print strftime("%M Minutes, %S Seconds",systime() - mktime($0))}' # تفاضل را به یک شکل قابل خواندن انسانی تبدیل میکند ،gawk مخصوص strftime() تابع
پرسش و پاسخ 70 (آخرین ویرایش 2013-04-10 21:27:34 توسط geirha)
ایست!
اول از همه، اگر شما واقعاً کلمه عبور خود را در جایی از اسکریپت تعبیه کنید، میتواند در تمام جهان قابل رؤیت بشود(یا حداقل، برای هر شخصی که بتواند فایلهای سیستم شما را بخواند). این امر تمامی هدف از داشتن کلمه عبور برای حساب راه دور شما را بر باد میدهد.
اگر تمام آنچه شما میخواهید، برای آنست که توسط ssh به کاربر اعلان کلمه ورود داده شود، واقعاً مطمئن شوید که اسکریپت شما در ترمینال اجرا میگردد و آن فرمان ssh شما در پیشزمینه اجرا میشود(به طور معمول). اگر سرویسدهنده راه دور کلمه عبوری برای اعتبارسنجی نیاز داشته باشد، ssh اعلانی برای کلمه عبور به کاربر میدهد. نیازی نیست اسکریپت شما با آن درگیر شود.
مخصوصاً، خودتان از کاربر کلمه عبورش را نپرسید که در یک اسکریپت ذخیره و سپس ارسال آن به ssh را آزمایش کنید. این کار به شدت امنیت شما را کاهش میدهد.
اگر میخواهید به طورکلی کلمه عبور تأیید اعتبار را کنار بگذارید، آنوقت به جای آن باید از public key authentication(کلید عمومی تصدیق اعتبار) استفاده کنید. صفحه man در مورد ssh-keygen(1) را بخوانید و بفهمید، یا برای یک مرور کوتاه، SshKeys را ببینید. این صفحه به شما میگوید که چگونه یک زوج کلید عمومی و خصوصی تولید کنید(در یکی از قالبهای RSA 1 یا DSA )، و چطور از این کلیدها بدون ارسال هیچ کلمه عبوری برای تصدیق هویت در سیستم راه دور استفاده کنید.
این هم یک خلاصه فشرده از طرز کار:
ssh-keygen -t rsa ssh me@remote "cat >> ~/.ssh/authorized_keys" < ~/.ssh/id_rsa.pub ssh me@remote date # اعلان ورود کلمه عبور نمیدهد # اما کلید شما میتواند یک عبارت عبور داشته باشد
اگر کلید شما شامل یک عبارت عبور باشد، و شما میخواهید از تایپ آن در هر نوبت اجتناب کنید، ssh-agent(1) را بررسی کنید. به هر حال این موضوع فراتر از محدوده این نوشته است. اگر اسکریپت شما باید به طور خودکار اجرا شود، آنوقت لازم است شما عبارت عبور را از کلید پاک کنید. این کار امنیت شما را کاهش میدهد، به علت آنکه بعد شخصی که کلید را برباید میتواند با عنوان شما به سرویسدهنده راه دور متصل شود( این معادل قرار دادن کلمه عبور در یک فایل است). اگر چه، گاهی اوقات با یک ریسک قابل قبول این کار صلاح دانسته میشود.
اگر حتی با یک کلید عمومی درج شده در فایل authorized_keys راه دور، به شما اعلان کلمه عبور داده میشود ،احتمال میرود شما مشکل مجوزها در سیستم راه دور دارید. برای بحث در مورد این قبیل مشکلات SshKeys را ملاحظه کنید.
اگر اینطور نیست، پس مطمئن شوید که املای آن به صورت authorised_keys نباشد. SSH از املای US به صورت authorized_keys استفاده میکند.
اگر شما واقعاً میخواهید به جای استفاده از کلیدهای عمومی، کلمه عبور را در یک متغیر ذخیره کنید و بعد آن را به برنامهای عبور بدهید، اول ببین آفتاب به سرت نتابیده. آنوقت، اگر , بازهم میخواهید از کلمه عبور استفاده کنید، expect(1) را به کار ببرید (یا empty(1) کمتر کلاسیک اما بیشتر موافق bash). اما از ما برای کمک در مورد آن نپرسید.
expect همچنین در انواع متفاوت مربوط به telnet یا FTP این پرسش صدق میکند. با این وجود هرکس که هنوز هم بدون یک دلیل خوب telnetd را اجرا میکند، لازم است اخراج و جایگزین بشود.
پرسش و پاسخ 69 (آخرین ویرایش 2011-11-08 14:23:33 توسط pgas)
مترجم: RSA نام متداولترین الگوریتم تهیه کلید عمومی و کلید خصوصی رمزنگاری میباشد، که از حروف اول نام ابداع کنندگان این روش اخذ گردیده است که سه نفر به نامهای Ron Rivest , Adi Shamir , Leonard Adleman میباشند، ایشان در سال 1977 این شیوه رمزنگاری را ابداع نمودند، امنیت RSA به استناد دشواری یافتن عوامل مؤثر در تولید اعداد خیلی بزرگ میباشد. در حال حاضر این دشواری، امنیت لازم را تامین مینماید اما ممکن است در آینده هکرها بتوانند روش آسانی برای غلبه بر آن ابداع کنند! شایان ذکر است که حق امتیاز RSA متعلق به شرکت امنیتی با همین نام بود که در سپتامبر سال 2000 منقضی گردیده است.
روش DSA نیز که سرنام Digital Signature Algorithm میباشد، یک استاندارد U.S. federal است که در سال 1991 توسط موسسه ملی تکنولوژی و استانداردها در امریکا تهیه گردیده است.
(بازگشت)
نخست بررسی کنید آیا میشود به فرمانی که اجرا میکنید به طور مستقیم گفته شود، زمان مورد نظر به پایان رسید. روشهای تشریح شده در اینجا فرافکنی hack مانندی برای مجبور نمودن دستور، به خاتمه یافتن پس از سپری شدن یک زمان معین میباشند. پیکربندی فرمان شما به طور صحیح، همواره نسبت به جایگزینهای ذیل ارجحیت دارد.
اگر فرمان هیچ پشتیبانی درونی از توقف پس از زمان تعیین شده نداشته باشد، آنوقت بهترین جایگزینها، برخی برنامههای خارجی به نام timeout و doalarm میباشند. بعضی توزیعهای لینوکس نگارش tct از timeout را به عنوان یک بسته ارائه میکنند. یک نگارش گنو از timeout نیز وجود دارد، که در انتشارهای اخیر coreutils ضمیمه گردیده است.
مراقب باشید: بعضی از پیادهسازیهای timeout به طور پیش فرض، یک سیگنال SIGKILL (kill -9) صادر میکنند، که تقریباً همان بیرون آوردن کابل برق است( یعنی از دست دادن هر شانس برنامه برای به انجام رساندن کارهایش که اغلب منجر به خراب شدن دادههایش میشود ). شما به جای آن باید از سیگنالی استفاده کنید که به برنامه اجازه بدهد خودش را خاموش کند (SIGTERM). برای اطلاعات بیشتر در باره SIGKILL، مدیریت پردازش را ملاحظه کنید.
تفاوت عمده بین doalarm و timeout آنست که doalarm برنامه را بعد از تنظیم مهلت مقرر به اجرا در میآورد، که در یک WrapperScript آن را شگفتآور میسازد، در حالیکه timeout برنامه را به عنوان یک فرزند شروع میکند و سپس همراه آن میماند( هر دو پردازش به طور همزمان وجود دارند)، که به ما مجال میدهد در صورت لزوم بیش از یک سیگنال ارسال کنیم.
اگر شما یکی از برنامههای فوق را ندارید یا نمیخواهید، میتوانید از پرل یک سطری برای تنظیم یک ALRM و سپس اجرای برنامهای که میخواهید تحت محدودیت زمانی اجرا گردد استفاده کنید. در هر حالت، شما باید بفهمید که برنامه شما با سیگنال SIGALRM چه کاری انجام میدهد، برنامههای دارای به هنگام سازیهای متناوب معمولاً به جای مرگ در موقعی که آن سیگنال را دریافت میکنند، برای این منظور از ALRM و به هنگام سازی، استفاده میکنند.
doalarm() { perl -e 'alarm shift; exec @ARGV' "$@"; } doalarm ${NUMBER_OF_SECONDS_BEFORE_ALRMING} program arg arg ...
اگر شما نمیتوانید یا نمیخواهید یکی از این برنامهها را به کار ببرید(که به راستی در هسته اصلی ابزارهای یونیکس در 30 سال قبل از این گنجانده شده بود!)، آنوقت بهترین کاری که میتوانید انجام بدهید، راه حل بدشکلی مانند این است:
command & pid=$! { sleep 10; kill $pid; } &
به طوری که فوراً متوجه خواهید شد، اگر آن را در پوسته محاورهای اجرا نمایید صرف نظر از اینکه وضعیت timeout شروع بشود یا نه، واقعاً یک بینظمی ایجاد خواهد کرد. پاک کردن آن سزاوار صرف وقت من نیست. همچنین، با هیچ فرمانی مانند top که به ترمینال پیشزمینه نیاز داشته باشد، نمیتواند به کار برود.
انجام کاری مشابه آن، اما نگهداری command در پیشزمینه امکانپذیر است:
bash -c '(sleep 10; kill $$) & exec command'
kill $$ پوسته را kill میکند، به استثنای آن exec باعث میشود فرمان PID پوسته را تحویل بگیرد. لازم است از bash -c استفاده شود برای این که پوسته فراخواننده تعویض نشود، در bash 4، استفاده از پوسته فرعی به جای آن امکانپذیر است:
( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec command )
اسکریپت پوسته "timeout" (با فرمان timeout اشتباه نشود) از رویکرد دوم در بالا استفاده میکند. مزیت آن کارکرد فوری آن است(نیازی به کامپایل شدن ندارد)، اما مشکلاتی دارد، به عنوان مثال با برنامههایی که از ورودی استاندارد میخوانند.
واقعاً، به جای آن فقط از timeout یا doalarm استفاده کنید.
پرسش و پاسخ 68 (آخرین ویرایش 2010-07-27 13:03:01 توسط GreyCat)
برای انجام این کار چند راه وجود دارد. بعضی از از این روشها ترفندهای خاصی را شامل میگردند که فقط با فضای سفید کار میکنند. برخی دیگر بیشتر عمومیت دارند، و میتوانند برای جدا کردن صفرها به کار بروند، و غیره.
در اینجا یکی از آنها که فقط برای فضاهای سفید کار میکند، آمده است. این کُد بر این واقعیت تکیه دارد که readدر صورتی که IFS برقرار نشده باشد، تمام فضاهای سفید ابتدا و انتها را پاک میکند:
# POSIX اما در صورتیکه متغیر شامل سطرجدید باشد شکست میخورد read -r var << EOF $var EOF
Bash میتواند کار مشابهی را با یک "here string" انجام بدهد:
# Bash read -rd '' x <<< "$x"
استفاده از یک رشته تهی به عنوان جداکننده به معنی آن است که read تمام آن رشته را از بین میبرد، به طوریکه NUL استفاده میشود. (به خاطر بیاورید: BASH فقط متغیرهای رشتهای C به کار میبرد.) این برای هر متنی ازجمله شامل سطرجدید مطمئن است.
این هم راه حلی با استفاده از extglob و بسط پارامتر همراه با یکدیگر:
# Bash shopt -s extglob x=${x##+([[:space:]])} x=${x%%+([[:space:]])}
همچنین این روش در پوسته Korn بدون ضرورت تنظیم صریح extglob کار میکند:
# ksh x=${x##+([[:space:]])} x=${x%%+([[:space:]])}
این روش آنطور که چند روش اول بودند، محدود به فضاهای سفید نیست. بعلاوه، صفرهای مقدم را میتوانید حذف کنید:
# Bash shopt -s extglob x=${x##+(0)}
روش دیگری در bash برای حذف صفرهای مقدم بر عدد، رفتار کردن با آنها به عنوان عدد صحیح در یک زمینه محاسباتی است:
# Bash x=$((10#$x)) # شامل هرچیز دیگری غیر از رقم باشد این روش ناموفق است x ،هر چند اگر
اگر در پوسته POSIX نیاز به پاک کردن صفرهای مقدم دارید، میتوانید یک حلقه به کار ببرید:
# POSIX while true; do case "$var" in 0*) var=${var#0};; *) break;; esac done
یا این ترفند( با تفصیل بیشتر در پرسش و پاسخ شماره 100 پوشش داده شده):
# POSIX zeroes=${var%%[!0]*} var=${var#$zeroes}
بسیار بسیار روشهای دیگری برای انجام این کار وجود دارد، برای نمونه استفاده از sed:
# POSIX, فضاهای سفید اول و انتهای هر سطر را موقوف میکند x=$(echo "$x" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
برای بریدن زوائد فایلهای بزرگ ، راه حلهای مبتنی بر برنامههای خارجی مانند sed بیشتر از متغیرهای پوسته مناسب میباشند.
پرسش و پاسخ 67 (آخرین ویرایش 2011-06-21 15:20:23 توسط GreyCat)