А можно обработать эту строку так, что она превратится в ряд команд awk. awk умеет печатать ascii-символы по десятичным кодам.
Вот только я awk не осилил.
Моя команда сильно раздута, потому что я не владею awk, часть работы переложил на sed. sed тут и не нужен.
Общий принцип следующий.
Команда awk 'BEGIN { printf "%c", 37; }' печатает символ, соответствующий коду 37. Нужно превратить исходную строку в подобие команды awk. Я использовал для этого sed.
sed 's/+/;/g' заменяет все плюсы на двоеточия.
s/char(\([0-9]*\))/printf "%c",\1/g заменяет char на printf "%c". При этом вместо \1 подставляется часть строки в скобках (числа).
Наконец, в начало добавляется BEGIN, в конец фигурная скобка. s/.*/BEGIN {&;}/ Тут .* соответствует всей строке. & — той подстроке, для которой выполняется замена, то есть, опять-таки, всей строке.
Если посмотреть на части конвейера:
$echo "char(37)+char(45)+char(125)+char(75)+char(66)" | sed 's/+/;/g;s/char(\([0-9]*\))/printf "%c",\1/g;s/.*/BEGIN {&;}/'
BEGIN {printf "%c",37;printf "%c",45;printf "%c",125;printf "%c",75;printf "%c",66;}
Вот это и есть простая команда awk.
К сожалению, я awk совсем не знаю, поэтому излишне сложное решение получилось. Так делать не нужно.
drBatty, а все ли echo такое умеют? echo, встроенная в bash умеет, echo из пакета GNU coreutils умеет, а вот ни встроенная в tcsh, ни /bin/echo в системе OpenBSD — увы нет.
sash-kan, как бы самому не превратиться из шерифа в индейца.
Кроме всевозможных BSD, есть еще и набор встраиваемых систем, где никакого GNU может и не оказаться. По мне, нужно всегда отдавать себе отчет, когда делаешь что-то нестандартное, что выходит, например, за рамки POSIX.
да. и более опасный - злоумышленнику проще будет пропихнуть свой вредоносный код в вашу смесь трёх разных языков, один из которых вы ещё и почти не знаете...
где никакого GNU может и не оказаться. По мне, нужно всегда отдавать себе отчет, когда делаешь что-то нестандартное, что выходит, например, за рамки POSIX.
суть в том, что в GNU вообще нет awk, есть gawk, которая ИМХО отличается от awk намного сильнее sed & bash.
где никакого GNU может и не оказаться. По мне, нужно всегда отдавать себе отчет, когда делаешь что-то нестандартное, что выходит, например, за рамки POSIX.
суть в том, что в GNU вообще нет awk, есть gawk, которая ИМХО отличается от awk намного сильнее sed & bash.
Спасибо, не знал.
Проверил, что выводит awk 'BEGIN { printf "%c",37 }' на разных системах.
OpenBSD 4.7, mawk в Squeeze (1.3.3-15), gawk (3.1.8) печатают проценты.
А вот mawk в Lenny не печатает вообще ничего…
sash-kan, как бы самому не превратиться из шерифа в индейца.
Кроме всевозможных BSD, есть еще и набор встраиваемых систем, где никакого GNU может и не оказаться. По мне, нужно всегда отдавать себе отчет, когда делаешь что-то нестандартное, что выходит, например, за рамки POSIX.
busybox должен помочь шерифу не впасть в индейство.
busybox должен помочь шерифу не впасть в индейство.
вот ещё какая переменная есть, и действует на многие команды (например на sed) POSIXLY_CORRECT
про gawk
Variables and fields may be (floating point) numbers, or strings, or both. How the value of a variable is
interpreted depends upon its context. If used in a numeric expression, it will be treated as a number; if
used as a string it will be treated as a string.
<skip>
When a string must be converted to a number, the conversion is accomplished using strtod(3). A number is
converted to a string by using the value of CONVFMT as a format string for sprintf(3), with the numeric
value of the variable as the argument.
а про символы вообще ничего не написано. т.е., как я понимаю, printf вообще не обязана переводить числа в символы, в отличие от printf(2)
7. For the c conversion specifier character: if the argument has a
numeric value, the character whose encoding is that value shall be
output. If the value is zero or is not the encoding of any charac‐
ter in the character set, the behavior is undefined. If the argu‐
ment does not have a numeric value, the first character of the
string value shall be output; if the string does not contain any
characters, the behavior is undefined.
Попробовал поосваивать awk, решение получилось довольно громоздким:
echo $FOO | awk '{ gsub(/(char\()|\)/,"");n=split($0,a,"+");for (i = 1; i <= n; i++) printf "%c",a[i]}'
проверил, работает и в GNU, и в OpenBSD.
printf "%c", 65 печатает именно A.
Согласно POSIX.
насколько я понял, только в POSIX-C. В С есть тип данных char, а вот в awk такого типа просто нет. Там есть числа и строки, а %c принимает аргумент всё-же char.
printf "%c", 65 печатает именно A.
Согласно POSIX.
насколько я понял, только в POSIX-C. В С есть тип данных char, а вот в awk такого типа просто нет. Там есть числа и строки, а %c принимает аргумент всё-же char.
(man 1p awk) писал(а):7. For the c conversion specifier character: if the argument has a numeric value, the character whose encoding is that value shall be output. If the value is zero or is not the encoding of any character in the character set, the behavior is undefined. If the argument does not have a numeric value, the first character of the string value shall be output; if the string does not contain any characters, the behavior is undefined.