Całkowita wartość ASCII do znaku w BASH przy użyciu printf

84

Charakter do wartości działa:

$ printf "%d\n" \'A
65
$ 

Mam dwa pytania, najważniejsze jest pierwsze:

  • Jak wziąć 65 i zamienić go na A?
  • \ 'A konwertuje znak ASCII na jego wartość za pomocą printf. Czy składnia jest specyficzna dla printf, czy jest używana gdziekolwiek indziej w BASH? (Takie małe ciągi są trudne dla Google).

źródło
W systemie Windows użyj ALT + 65, aby wydrukować znak ASCII - niestety to nie zadziała z Uniksem / bash;)
schnaader
2
@schnaader, ale nie możesz tego napisać.
ctrl-alt-delor
2
@richard: Errr .. to nie jest łatwe ani praktyczne, ale możesz :) „Po prostu” uruchom maszynę wirtualną z systemem Windows lub MS-DOS, wyślij „echo”, ALT, 6, 5, „> mysharedfolder \ file.txt” jako naciśnięcia klawiszy i odczytaj plik file.txt z udostępnionego folderu maszyny wirtualnej.
schnaader
2
@schnaader, czy możesz do tego użyć wina?
emory

Odpowiedzi:

69

Jedna linia

printf "\x$(printf %x 65)"

Dwie linie

set $(printf %x 65)
printf "\x$1"

Oto jeden, jeśli nie masz nic przeciwko używaniu awk

awk 'BEGIN{printf "%c", 65}'
poszerzać
źródło
3
Powinno też działaćprintf "$(printf '\\x%02x' $char)"
0andriy
31

To działa (z wartością ósemkową):

$ printf '%b' '\101'
A

nawet dla (niektórych: nie przekraczaj 7) sekwencji:

$ printf '%b' '\'{101..107}
ABCDEFG

Ogólna konstrukcja, która dopuszcza (dziesiętne) wartości w dowolnym zakresie, to:

$ printf '%b' $(printf '\\%03o' {65..122})
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz

Lub możesz użyć wartości szesnastkowych znaków:

$ printf '%b' $(printf '\\x%x' {65..122})
ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz

Możesz również odzyskać znak za pomocą xxd (użyj wartości szesnastkowych):

$ echo "41" | xxd -p -r
A

Oznacza to, że jedno działanie jest odwrotnością drugiego:

$ printf "%x" "'A" | xxd -p -r
A

Działa również z kilkoma wartościami szesnastkowymi jednocześnie:

$ echo "41 42 43 44 45 46 47 48 49 4a" | xxd -p -r
ABCDEFGHIJ

lub sekwencje (printf służy tutaj do uzyskania wartości szesnastkowych):

$ printf '%x' {65..90} | xxd -r -p 
ABCDEFGHIJKLMNOPQRSTUVWXYZ

Lub nawet użyj awk:

$ echo 65 | awk '{printf("%c",$1)}'
A

nawet dla sekwencji:

$ seq 65 90 | awk '{printf("%c",$1)}'
ABCDEFGHIJKLMNOPQRSTUVWXYZ

źródło
14

W przypadku drugiego pytania składnia cudzysłowu wiodącego ( \'A) jest specyficzna dla printf:

Jeżeli znak wiodący jest cudzysłowem pojedynczym lub cudzysłowem podwójnym, wartość jest wartością liczbową w bazowym zestawie kodów znaku następującego po cudzysłowie pojedynczym lub cudzysłowie podwójnym.

Z http://pubs.opengroup.org/onlinepubs/009695399/utilities/printf.html

David Hu
źródło
9

Jedną z opcji jest bezpośrednie wprowadzenie interesującego Cię znaku przy użyciu notacji szesnastkowej lub ósemkowej:

printf "\x41\n"
printf "\101\n"
Naaff
źródło
8

Do tego rodzaju konwersji używam perla:

perl -e 'printf "%c\n", 65;'
mouviciel
źródło
2
lub w perlu wypisz chr (65), "\ n"; Chociaż perl może być dobrym wyborem, jeśli robisz dużo takich rzeczy, użycie printf powłoki do konwersji twojej liczby na coś, co może przejść do sekwencji ucieczki \ 0, działa dobrze. Bardziej złożone z Unicode, ponieważ potrzebujesz \ u wsparcia w swoim printf.
Peter Cordes
Niestety, Perl to zapomniany język. Lepszy jest Python, który jest teraz dostępny na prawie każdym komputerze z systemem Linux. Ponadto pytanie dotyczy Shell-Bash, a nie innych platform!
s3n0
7

Jeśli chcesz zapisać wartość ASCII znaku: (zrobiłem to w BASH i zadziałało)

{
char="A"

testing=$( printf "%d" "'${char}" )

echo $testing}

wyjście: 65

MagicMercury86
źródło
To zadziałało, dzięki. Chciałem uzyskać liczbę całkowitą (kod ASCII) z wpisanego znaku. Zrobiłem skrypt: {przeczytaj -n 1 c; echo $ (printf "% d" "'$ {c}")}
Phaedrus
4

Jeśli przekonwertujesz 65na szesnastkowy, to 0x41:

$ echo -e "\x41" A

Cyber ​​Oliveira
źródło
jeśli znasz wartość szesnastkową, aby wydrukować znak ASCII$ printf "\x41"
katta
4

Wielkie litery:

i=67
letters=({A..Z})
echo "${letters[$i-65]}"

Wynik:

do
Cyrus
źródło
3

Oto kolejny sposób zamiany 65 na A (przez ósemkę):

help printf  # in Bash
man bash | less -Ip '^[[:blank:]]*printf'

printf "%d\n" '"A'
printf "%d\n" "'A"

printf '%b\n' "$(printf '\%03o' 65)"

Aby wyszukać w man bashcelu \'użycia (choć w tym przypadku daremne):

man bash | less -Ip "\\\'"  # press <n> to go through the matches
chand
źródło
1

wypisuje wszystkie "drukowalne" znaki twojej podstawowej konfiguracji basha:

printf '%b\n' $(printf '\\%03o' {30..127})

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
AG6HQ
źródło