जवाबों:
इन दो कार्यों को परिभाषित करें (आमतौर पर अन्य भाषाओं में उपलब्ध):
chr() {
[ "$1" -lt 256 ] || return 1
printf "\\$(printf '%03o' "$1")"
}
ord() {
LC_CTYPE=C printf '%d' "'$1"
}
उपयोग:
chr 65
A
ord A
65
printf "\\$(printf '%03o' "$1")"
, '%03o'
, LC_CTYPE=C
और में एकल उद्धरण "'$1"
करते?
आप इसके साथ पूरा सेट देख सकते हैं:
$ man ascii
आपको ऑक्टल, हेक्स और दशमलव में टेबल मिलेंगे।
यदि आप इसे UTF-8 वर्णों तक विस्तारित करना चाहते हैं:
$ perl -CA -le 'print ord shift' 😈
128520
$ perl -CS -le 'print chr shift' 128520
😈
के साथ bash
, ksh
या zsh
निर्मित:
$ printf "\U$(printf %08x 128520)\n"
😈
iceweasel
पर Debian sid
। जैसा कि iceweasel के वेब कंसोल द्वारा पुष्टि किया गया फ़ॉन्ट "DejaVu Sans" है और मुझे ttf-dejavu ttf-dejavu-core ttf-dejavu-extra पैकेज स्थापित किए गए हैं जो डेबियन के साथ dejavu-fonts.org
यह अच्छा काम करता है,
echo "A" | tr -d "\n" | od -An -t uC
echo "A" ### Emit a character.
| tr -d "\n" ### Remove the "newline" character.
| od -An -t uC ### Use od (octal dump) to print:
### -An means Address none
### -t select a type
### u type is unsigned decimal.
### C of size (one) char.
इसके बराबर:
echo -n "A" | od -An -tuC ### Not all shells honor the '-n'.
echo -n
दमन की जरूरत को खत्म करने वाली न्यूलाइन को दबाता हैtr -d "\n"
echo
, उदाहरण के लिए यूनिक्स आज्ञाकारी इकोस में नहीं। printf %s A
पोर्टेबल एक होगा।
मैं सरल (और सुरुचिपूर्ण?) बैश समाधान के लिए जा रहा हूं:
for i in {a..z}; do echo $(printf "%s %d" "$i" "'$i"); done
एक स्क्रिप्ट के लिए आप निम्नलिखित का उपयोग कर सकते हैं:
CharValue="A"
AscValue=`printf "%d" "'$CharValue"
CharValue से पहले एकल उद्धरण नोटिस। यह बाध्य है ...
printf "%d"
।
ctbl() for O in 0 1 2 3
do for o in 0 1 2 3 4 5 6 7
do for _o in 7 6 5 4 3 2 1 0
do case $((_o=(_o+=O*100+o*10)?_o:200)) in
(*00|*77) set "${1:+ \"}\\$_o${1:-\"}";;
(140|42) set '\\'"\\$_o$1" ;;
(*) set "\\$_o$1" ;esac
done; printf "$1"; shift
done
done
eval '
ctbl(){
${1:+":"} return "$((OPTARG=0))"
set "" "" "${1%"${1#?}"}"
for c in ${a+"a=$a"} ${b+"b=$b"} ${c+"c=$c"}\
${LC_ALL+"LC_ALL=$LC_ALL"}
do while case $c in (*\'\''*) ;; (*) ! \
set "" "${c%%=*}='\''${c#*=}$1'\'' $2" "$3"
esac;do set "'"'\''\${c##*\'}"'$@"; c=${c%\'\''*}
done; done; LC_ALL=C a=$3 c=;set "" "$2 OPTARG='\''${#a}*("
while [ 0 -ne "${#a}" ]
do case $a in ([[:print:][:cntrl:]]*)
case $a in (['"$(printf \\1-\\77)"']*)
b=0;; (*) b=1
esac;; (['"$( printf \\200-\\277)"']*)
b=2;; (*) b=3
esac; set '"$(ctbl)"' "$@"
eval " set \"\${$((b+1))%"'\''"${a%"${a#?}"}"*}" "$6"'\''
a=${a#?};set "$((b=b*100+${#1}+${#1}/8*2)))" \
"$2(o$((c+=1))=$b)>=(d$c=$((0$b)))|"
done; eval " unset LC_ALL a b c;${2%?})'\''"
return "$((${OPTARG%%\**}-1))"
}'
पहला ctbl()
- वहां सबसे ऊपर - केवल एक बार ही चलता है। यह निम्न आउटपुट उत्पन्न करता है (जिसे sed -n l
प्रिंट करने योग्यता के लिए फ़िल्टर किया गया है ) :
ctbl | sed -n l
"\200\001\002\003\004\005\006\a\b\t$
\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\
\035\036\037 !\\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRS\
TUVWXYZ[\\]^_\\`abcdefghijklmnopqrstuvwxyz{|}~\177" "\200\201\202\203\
\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\
\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\
\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\
\267\270\271\272\273\274\275\276\277" "\300\301\302\303\304\305\306\
\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\
\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\
\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\
\372\373\374\375\376\377"$
... जो सभी 8-बिट बाइट्स (कम NUL
) हैं , चार शेल-उद्धृत स्ट्रिंग्स में विभाजित हैं जो समान रूप से 64-बाइट सीमाओं पर विभाजित हैं। तार की तरह अष्टाधारी सीमाओं के साथ प्रतिनिधित्व किया जा सकता है \200\1-\77
, \100-\177
, \200-\277
, \300-\377
, जहां बाइट 128 के लिए एक जगह-धारक के रूप में प्रयोग किया जाता है NUL
।
ctbl()
अस्तित्व के लिए पहला उद्देश्य उन तारों को उत्पन्न करना है ताकि उसके बाद eval
दूसरे ctbl()
फ़ंक्शन को शाब्दिक रूप से एम्बेडेड किया जा सके। इस तरह उन्हें फ़ंक्शन में संदर्भित किया जा सकता है बिना जरूरत के उन्हें हर बार फिर से उत्पन्न करने की आवश्यकता होती है। जब eval
दूसरे ctbl()
फ़ंक्शन को परिभाषित करता है तो पहला होना बंद हो जाएगा।
दूसरे ctbl()
फ़ंक्शन का शीर्ष आधा भाग यहां अधिकतर सहायक है - इसे किसी भी वर्तमान शेल स्थिति को पोर्टेबली और सुरक्षित रूप से डिज़ाइन करने के लिए डिज़ाइन किया गया है जब इसे कहा जाता है तो यह प्रभावित हो सकता है। शीर्ष लूप किसी भी वैरिएबल के मूल्यों में किसी भी उद्धरण को उद्धृत करेगा, जिसे वह उपयोग करना चाहता है, और फिर उसके सभी मापदंडों में परिणाम को स्टैक कर सकता है।
हालाँकि, पहली दो पंक्तियाँ, पहले तुरंत 0 लौटती हैं और $OPTARG
उसी पर सेट होती हैं यदि फ़ंक्शन के पहले तर्क में कम से कम एक वर्ण नहीं होता है। और अगर ऐसा होता है, तो दूसरी पंक्ति तुरंत अपने पहले तर्क को केवल उसके पहले चरित्र को काट देती है - क्योंकि फ़ंक्शन केवल एक समय में एक चरित्र को संभालता है। महत्वपूर्ण रूप से, यह वर्तमान स्थानीय संदर्भ में ऐसा करता है, जिसका अर्थ है कि यदि एक चरित्र में एक से अधिक बाइट शामिल हो सकते हैं, तो, बशर्ते कि शेल बहु-बाइट वर्णों का ठीक से समर्थन करता है, यह किसी भी बाइट को नहीं छोड़ेगा, सिवाय उन जो कि नहीं हैं इसके पहले तर्क का पहला चरित्र।
${1:+":"} return "$((OPTARG=0))"
set "" "" "${1%"${1#?}"}"
यदि आवश्यक हो तो यह सेव लूप करता है, और बाद में यह LC_ALL
वेरिएबल को असाइन करके हर श्रेणी के लिए सी लोकेल में वर्तमान लोकेल के संदर्भ को फिर से परिभाषित करता है । इस बिंदु से, एक चरित्र में केवल एक ही बाइट शामिल हो सकती है, और इसलिए यदि इसके पहले तर्क के पहले चरित्र में कई बाइट्स थे, तो अब प्रत्येक को अपने स्वयं के व्यक्तिगत पात्रों के रूप में पता होना चाहिए।
LC_ALL=C
यह इस कारण से है कि फ़ंक्शन का दूसरा आधा एक while
लूप है , जैसा कि एक एकल रन अनुक्रम के विपरीत है। ज्यादातर मामलों में यह संभवतः केवल एक बार कॉल के अनुसार निष्पादित होगा, लेकिन, यदि शेल को ctbl()
ठीक से परिभाषित किया गया है जो मल्टी-बाइट वर्णों को संभालता है, तो यह लूप हो सकता है।
while [ 0 -ne "${#a}" ]
do case $a in ([[:print:][:cntrl:]]*)
case $a in (['"$(printf \\1-\\77)"']*)
b=0;; (*) b=1
esac;; (['"$( printf \\200-\\277)"']*)
b=2;; (*) b=3
esac; set '"$(ctbl)"' "$@"
ध्यान दें कि उपरोक्त $(ctbl)
कमांड प्रतिस्थापन केवल एक बार मूल्यांकन किया जाता है - eval
जब फ़ंक्शन शुरू में परिभाषित होता है - और उसके बाद हमेशा के लिए टोकन को उस कमांड प्रतिस्थापन के शाब्दिक आउटपुट से बदल दिया जाता है क्योंकि शेल की मेमोरी में सहेजा गया है। दो case
पैटर्न कमांड प्रतिस्थापन के बारे में भी यही सच है । यह फ़ंक्शन कभी भी सबस्क्रिप्शन या किसी अन्य कमांड को कॉल नहीं करता है। यह इनपुट / आउटपुट को पढ़ने या लिखने का प्रयास कभी नहीं करेगा (कुछ शेल डायग्नोस्टिक संदेश के मामले को छोड़कर - जो शायद बग को इंगित करता है) ।
यह भी ध्यान दें कि लूप निरंतरता के लिए परीक्षण बस नहीं है [ -n "$a" ]
, क्योंकि, जैसा कि मैंने अपनी हताशा के लिए पाया, किसी कारण से एक bash
शेल करता है:
char=$(printf \\1)
[ -n "$char" ] || echo but it\'s not null\!
but it's not null!
... और इसलिए मैं स्पष्ट रूप से $a
प्रत्येक पुनरावृत्ति के लिए 0 से तुलना कर रहा हूं , जो कि बेवजह, अलग तरीके से व्यवहार भी करता है (पढ़ें: सही ढंग से) ।
case
चेकों हमारे चार तार और दुकानों में बाइट के सेट के लिए एक संदर्भ में से किसी में शामिल करने के लिए पहली बाइट $b
। इसके बाद शेल के पहले चार स्थितिगत पैरामीटर, पूर्ववर्ती द्वारा लिखे और लिखे गए set
तार के हैं ।eval
ctbl()
अगला, जो भी पहले तर्क का अवशेष है, उसे फिर से अस्थायी रूप से उसके पहले चरित्र में काट दिया जाता है - जिसे अब एकल बाइट होने का आश्वासन दिया जाना चाहिए। यह पहली बाइट स्ट्रिंग जो यह मेल खाते हैं और में संदर्भ की पूंछ से पट्टी के लिए एक संदर्भ के रूप में प्रयोग किया जाता है $b
है eval
एक स्थितीय पैरामीटर प्रतिनिधित्व करने के लिए तो स्ट्रिंग में पिछले बाइट के संदर्भ बाइट से सब कुछ दूर प्रतिस्थापित किया जा सकता 'घ। अन्य तीन तार पूरी तरह से स्थितीय मापदंडों से गिराए जाते हैं।
eval " set \"\${$((b+1))%"'\''"${a%"${a#?}"}"*}" "$6"'\''
a=${a#?};set "$((b=b*100+${#1}+${#1}/8*2)))" \
"$2(o$((c+=1))=$b)>=(d$c=$((0$b)))|"
इस बिंदु पर बाइट का मान (मोडुलो 64) स्ट्रिंग के लेन के रूप में संदर्भित किया जा सकता है:
str=$(printf '\200\1\2\3\4\5\6\7')
ref=$(printf \\4)
str=${str%"$ref"*}
echo "${#str}"
4
थोड़ा गणित तब मूल्य के आधार पर मापांक के साथ सामंजस्य स्थापित करने के लिए किया जाता है $b
, पहले बाइट $a
को स्थायी रूप से छीन लिया जाता है, और वर्तमान चक्र के लिए आउटपुट लूप रीसायकल से पहले एक स्टैक लंबित पूरा करने के लिए जोड़ा जाता है ताकि यह जांचा जा सके कि $a
क्या वास्तव में खाली है।
eval " unset LC_ALL a b c;${2%?})'\''"
return "$((${OPTARG%%\**}-1))"
जब $a
निश्चित रूप से खाली होता है, तो सभी नाम और राज्य - इसके अपवाद के साथ $OPTARG
- कि इसके निष्पादन के दौरान प्रभावित फ़ंक्शन को उनकी पिछली स्थिति में पुनर्स्थापित किया जाता है - चाहे सेट और शून्य, सेट और अशक्त, या परेशान न हों - और आउटपुट सहेजा जाता है करने के लिए $OPTARG
फ़ंक्शन के रूप में। वास्तविक रिटर्न मूल्य इसके पहले तर्क के पहले चरित्र में बाइट्स की कुल संख्या से कम है - इसलिए कोई भी एकल बाइट चरित्र शून्य पर लौटता है और कोई भी मल्टी-बाइट चार शून्य से अधिक वापस आ जाएगा - और इसका आउटपुट स्वरूप थोड़ा अजीब है।
मूल्य ctbl()
के लिए बचाता है $OPTARG
एक वैध खोल अंकगणितीय अभिव्यक्ति है कि, अगर मूल्यांकन किया, समवर्ती रूपों में से चर नाम सेट हो जाएगा है $o1
, $d1
, $o2
, $d2
दशमलव में और उसके पहले तर्क के पहले अक्षर में सभी संबंधित बाइट्स की अष्टाधारी मूल्यों, लेकिन अंत में कुल करने के लिए मूल्यांकन करने के लिए इसके पहले तर्क में बाइट्स की संख्या। यह लिखते समय मेरे मन में एक विशेष प्रकार का कार्यप्रवाह था, और मुझे लगता है कि शायद एक प्रदर्शन क्रम में है।
मुझे अक्सर इसके साथ एक स्ट्रिंग लेने का एक कारण मिलता है getopts
:
str=some\ string OPTIND=1
while getopts : na -"$str"
do printf %s\\n "$OPTARG"
done
s
o
m
e
s
t
r
i
n
g
मैं शायद एक छोटे से अधिक सिर्फ यह प्रति पंक्ति एक प्रिंट, लेकिन कुछ भी संभव है। किसी भी मामले में, मैं नहीं अभी तक एक पाया getopts
कि ठीक से करना होगा (हड़ताल है कि - dash
की getopts
यह चार से चार करता है, लेकिन bash
निश्चित रूप से नहीं करता है) :
str=ŐőŒœŔŕŖŗŘřŚśŜŝŞş OPTIND=1
while getopts : na -"$str"
do printf %s\\n "$OPTARG"
done| od -tc
0000000 305 \n 220 \n 305 \n 221 \n 305 \n 222 \n 305 \n 223 \n
0000020 305 \n 224 \n 305 \n 225 \n 305 \n 226 \n 305 \n 227 \n
0000040 305 \n 230 \n 305 \n 231 \n 305 \n 232 \n 305 \n 233 \n
0000060 305 \n 234 \n 305 \n 235 \n 305 \n 236 \n 305 \n 237 \n
0000100
ठीक। इसलिए मैंने कोशिश की ...
str=ŐőŒœŔŕŖŗŘřŚśŜŝŞş
while [ 0 -ne "${#str}" ]
do printf %c\\n "$str" #identical results for %.1s
str=${str#?}
done| od -tc
#dash
0000000 305 \n 220 \n 305 \n 221 \n 305 \n 222 \n 305 \n 223 \n
0000020 305 \n 224 \n 305 \n 225 \n 305 \n 226 \n 305 \n 227 \n
0000040 305 \n 230 \n 305 \n 231 \n 305 \n 232 \n 305 \n 233 \n
0000060 305 \n 234 \n 305 \n 235 \n 305 \n 236 \n 305 \n 237 \n
0000100
#bash
0000000 305 \n 305 \n 305 \n 305 \n 305 \n 305 \n 305 \n 305 \n
*
0000040
इस तरह के वर्कफ़्लो - बाइट के लिए बाइट / चार के लिए चार तरह से - एक मैं अक्सर ट्टी सामान करते समय मिलता है। इनपुट के अग्रणी किनारे पर आपको चार मूल्यों को जानने की आवश्यकता है जैसे ही आप उन्हें पढ़ते हैं, और आपको उनके आकार की आवश्यकता होती है (विशेषकर कॉलम की गिनती करते समय) , और आपको पूरे वर्ण होने के लिए पात्रों की आवश्यकता होती है ।
और इसलिए अब मेरे पास है ctbl()
:
str=ŐőŒœŔŕŖŗŘřŚśŜŝŞş
while [ 0 -ne "${#str}" ]
do ctbl "$str"
printf "%.$(($OPTARG))s\t::\t$OPTARG\t::\t$?\t::\t\\$o1\\$o2\n" "$str"
str=${str#?}
done
Ő :: 2*((o1=305)>=(d1=197)|(o2=220)>=(d2=144)) :: 1 :: Ő
ő :: 2*((o1=305)>=(d1=197)|(o2=221)>=(d2=145)) :: 1 :: ő
Œ :: 2*((o1=305)>=(d1=197)|(o2=222)>=(d2=146)) :: 1 :: Œ
œ :: 2*((o1=305)>=(d1=197)|(o2=223)>=(d2=147)) :: 1 :: œ
Ŕ :: 2*((o1=305)>=(d1=197)|(o2=224)>=(d2=148)) :: 1 :: Ŕ
ŕ :: 2*((o1=305)>=(d1=197)|(o2=225)>=(d2=149)) :: 1 :: ŕ
Ŗ :: 2*((o1=305)>=(d1=197)|(o2=226)>=(d2=150)) :: 1 :: Ŗ
ŗ :: 2*((o1=305)>=(d1=197)|(o2=227)>=(d2=151)) :: 1 :: ŗ
Ř :: 2*((o1=305)>=(d1=197)|(o2=230)>=(d2=152)) :: 1 :: Ř
ř :: 2*((o1=305)>=(d1=197)|(o2=231)>=(d2=153)) :: 1 :: ř
Ś :: 2*((o1=305)>=(d1=197)|(o2=232)>=(d2=154)) :: 1 :: Ś
ś :: 2*((o1=305)>=(d1=197)|(o2=233)>=(d2=155)) :: 1 :: ś
Ŝ :: 2*((o1=305)>=(d1=197)|(o2=234)>=(d2=156)) :: 1 :: Ŝ
ŝ :: 2*((o1=305)>=(d1=197)|(o2=235)>=(d2=157)) :: 1 :: ŝ
Ş :: 2*((o1=305)>=(d1=197)|(o2=236)>=(d2=158)) :: 1 :: Ş
ş :: 2*((o1=305)>=(d1=197)|(o2=237)>=(d2=159)) :: 1 :: ş
ध्यान दें कि ctbl()
वास्तव में $[od][12...]
चर को परिभाषित नहीं किया जाता है - इसका कभी भी किसी भी राज्य पर कोई स्थायी प्रभाव नहीं होता है $OPTARG
- लेकिन केवल स्ट्रिंग में डाल देता $OPTARG
है उन्हें परिभाषित करने के लिए इस्तेमाल किया जा सकता है - यही कारण है कि मुझे प्रत्येक वर्ण की दूसरी प्रति मिलती है printf "\\$o1\\$o2"
क्योंकि वे हर बार जब मैं मूल्यांकन करते हैं तो सेट होते हैं $(($OPTARG))
। लेकिन मैं यह भी एक क्षेत्र लंबाई संशोधक करने की घोषणा कर रहा हूँ जहाँ मैं यह कर printf
की %s
स्ट्रिंग विवाद प्रारूप है, और क्योंकि अभिव्यक्ति हमेशा एक चरित्र में बाइट की कुल संख्या का आकलन करती है, मैं जब मैं कर उत्पादन पर पूरे चरित्र मिलता है:
printf %.2s "$str"
[ "$(printf \\1)" ]|| ! echo but its not null!
जब तक आप इस तरह की वास्तविक प्रतियोगिता की अनुशंसा नहीं करते, तब तक कृपया देखें , इस बीच कृपया देखें , सार्थक टिप्पणी अभ्यास के साथ अपने आप को बेहतर ढंग से परिचित करने के लिए स्वतंत्र महसूस करें ...?
sh
कमांड भाषा है। bash
एक है सीमा फिर से देखभाल किसी भी प्रकार की व्यापक रूप से पोर्टेबल, आत्म विस्तार और नाम स्थान माननीय चरित्र आकार की ओर से ऊपर समर्थ बनाया के ज्यादा के लिए बड़े हिस्से में एक ही की supraset, और एक तेज़ प्रेरक। bash
पहले से ही इसे संभालना चाहिए, लेकिन c
भाषा printf
थी, और शायद, ऊपर दी गई क्षमता की कमी है।
शेल स्क्रिप्ट नहीं है, लेकिन काम करता है
awk 'BEGIN{for( i=97; i<=122;i++) printf "%c %d\n",i,i }'
नमूना उत्पादन
xieerqi:$ awk 'BEGIN{for( i=97; i<=122;i++) printf "%c %d\n",i,i }' | head -n 5
a 97
b 98
c 99
d 100
e 101
konsole
xxd<press enter>
<SHIFT+INSERT><CTRL+D>
आपको कुछ ऐसा मिलता है:
mariank@dd903c5n1 ~ $ xxd
û0000000: fb
आपको पता है कि आपके द्वारा चिपकाए गए प्रतीक में हेक्स कोड है 0xfb
"'A"
सही है जबकि यदि आप इसका उपयोग"A"
करते हैं तो कहेंगेA: invalid number
:। ऐसा लगता है कि यह प्रिंटफ साइड पर किया गया है (यानी, शेल में,"'A"
वास्तव में 2 वर्ण है, a'
और aA
। जो प्रिंटफ के हैं। और प्रिंटफ संदर्भ में, इसे A के ascii मान में बदल दिया जाता है, और अंत में इसे प्रिंट किया जाता है) दशमलव के रूप में धन्यवाद'%d'
।'Ox%x'
हेक्सा में दिखाने के लिए या'0%o'
इसे अष्टक में उपयोग करने के लिए))