addstr — код, вывод:
use Curses;
initscr;
addstr 0, 0, 'Ж 会 र';
addstr 1, 0, 'Curses ' . Curses->VERSION . ", perl $^V" . ", OS: $^O";
getch;
endwin;
Ж 会 र
Curses 1.43, perl v5.36.0, OS: openbsd
addstring — код, вывод:
use Curses;
initscr;
addstring 0, 0, 'Ж 会 र';
addstring 1, 0, 'Curses ' . Curses->VERSION . ", perl $^V" . ", OS: $^O";
getchar;
endwin;
Ð~V ä¼~Z र
Curses 1.43, perl v5.36.0, OS: openbsd
Почему наблюдается такое поведение?
Разве не должно быть наоборот, поскольку addstr является устаревшим, а addstring предназначен для поддержки юникода?
https://metacpan.org/pod/Curses#Wide-Character-Aware-Functions
https://metacpan.org/pod/Curses#Available-Wide-Character-Aware-Functions
Более широкий пример со строкой юникода:
openНам нужен файл со строкой в юникоде:
echo -n 'Ж 会 र' > unicode.string.txt
addstr, без дополнительных объявлений:use Curses;
my $unicode_string_variable = 'Ж 会 र';
my $unicode_string_argv = $ARGV[0];
my $unicode_string_backticks = `cat unicode.string.txt`;
open my $open_pipe_read_handle, '-|', 'cat', 'unicode.string.txt' || die;
my $unicode_string_open_pipe = <$open_pipe_read_handle>;
# print unicode to files
open my $hardcoded_handle, '>', 'unicode.string.hardcoded' || die;
print $hardcoded_handle 'Ж 会 र';
close $hardcoded_handle;
open my $variable_handle, '>', 'unicode.string.variable' || die;
print $variable_handle $unicode_string_variable;
close $variable_handle;
open my $argv_handle, '>', 'unicode.string.argv' || die;
print $argv_handle $unicode_string_argv;
close $argv_handle;
open my $backticks_handle, '>', 'unicode.string.backticks' || die;
print $backticks_handle $unicode_string_backticks;
close $backticks_handle;
open my $open_pipe_handle, '>', 'unicode.string.open_pipe' || die;
print $open_pipe_handle $unicode_string_open_pipe;
close $open_pipe_handle;
# print unicode to STDOUT
printf "%s: %s\n", 'hardcoded', 'Ж 会 र';
printf "%s: %s\n", 'variable ', $unicode_string_variable;
printf "%s: %s\n", 'argv ', $unicode_string_argv;
printf "%s: %s\n", 'backticks', $unicode_string_backticks;
printf "%s: %s\n", 'open_pipe', $unicode_string_open_pipe;
initscr;
# print unicode to Curses
addstr 0, 0, 'hardcoded: ' . 'Ж 会 र';
addstr 1, 0, 'variable : ' . $unicode_string_variable;
addstr 2, 0, 'argv : ' . $unicode_string_argv;
addstr 3, 0, 'backticks: ' . $unicode_string_backticks;
addstr 4, 0, 'open_pipe: ' . $unicode_string_open_pipe;
addstr 5, 0, 'Curses ' . Curses->VERSION . ", perl $^V" . ", OS: $^O";
getchar;
endwin;
бегать:
perl curses-unicode.addstr.pl 'Ж 会 र'
Вывод ругательств, всерабочий юникод:
hardcoded: Ж 会 र
variable : Ж 会 र
argv : Ж 会 र
backticks: Ж 会 र
open_pipe: Ж 会 र
Curses 1.43, perl v5.36.0, OS: openbsd
Выход STDOUT, всерабочий юникод:
hardcoded: Ж 会 र
variable : Ж 会 र
argv : Ж 会 र
backticks: Ж 会 र
open_pipe: Ж 会 र
Вывод файлов, всерабочий юникод:
cat unicode.string.*
Ж 会 रЖ 会 रЖ 会 रЖ 会 रЖ 会 रЖ 会 र
addstring, без дополнительных объявлений:use Curses;
my $unicode_string_variable = 'Ж 会 र';
my $unicode_string_argv = $ARGV[0];
my $unicode_string_backticks = `cat unicode.string.txt`;
open my $open_pipe_read_handle, '-|', 'cat', 'unicode.string.txt' || die;
my $unicode_string_open_pipe = <$open_pipe_read_handle>;
# print unicode to files
open my $hardcoded_handle, '>', 'unicode.string.hardcoded' || die;
print $hardcoded_handle 'Ж 会 र';
close $hardcoded_handle;
open my $variable_handle, '>', 'unicode.string.variable' || die;
print $variable_handle $unicode_string_variable;
close $variable_handle;
open my $argv_handle, '>', 'unicode.string.argv' || die;
print $argv_handle $unicode_string_argv;
close $argv_handle;
open my $backticks_handle, '>', 'unicode.string.backticks' || die;
print $backticks_handle $unicode_string_backticks;
close $backticks_handle;
open my $open_pipe_handle, '>', 'unicode.string.open_pipe' || die;
print $open_pipe_handle $unicode_string_open_pipe;
close $open_pipe_handle;
# print unicode to STDOUT
printf "%s: %s\n", 'hardcoded', 'Ж 会 र';
printf "%s: %s\n", 'variable ', $unicode_string_variable;
printf "%s: %s\n", 'argv ', $unicode_string_argv;
printf "%s: %s\n", 'backticks', $unicode_string_backticks;
printf "%s: %s\n", 'open_pipe', $unicode_string_open_pipe;
initscr;
# print unicode to Curses
addstring 0, 0, 'hardcoded: ' . 'Ж 会 र';
addstring 1, 0, 'variable : ' . $unicode_string_variable;
addstring 2, 0, 'argv : ' . $unicode_string_argv;
addstring 3, 0, 'backticks: ' . $unicode_string_backticks;
addstring 4, 0, 'open_pipe: ' . $unicode_string_open_pipe;
addstring 5, 0, 'Curses ' . Curses->VERSION . ", perl $^V" . ", OS: $^O";
getchar;
endwin;
бегать:
perl curses-unicode.addstring.pl 'Ж 会 र'
Вывод ругательств, весь битый юникод::
hardcoded: Ð~V ä¼~Z र
variable : Ð~V ä¼~Z र
argv : Ð~V ä¼~Z र
backticks: Ð~V ä¼~Z र
open_pipe: Ð~V ä¼~Z र
Curses 1.43, perl v5.36.0, OS: openbsd
Вывод STDOUT, всерабочий юникод::
hardcoded: Ж 会 र
variable : Ж 会 र
argv : Ж 会 र
backticks: Ж 会 र
open_pipe: Ж 会 र
Вывод файлов, всерабочий юникод:
cat unicode.string.*
Ж 会 रЖ 会 रЖ 会 रЖ 会 रЖ 会 रЖ 会 र
addstring, дополнительные объявления use utf8, -CA и :encoding(UTF-8):use utf8;
use Curses;
my $unicode_string_variable = 'Ж 会 र';
my $unicode_string_argv = $ARGV[0];
my $unicode_string_backticks = `cat unicode.string.txt`;
open my $open_pipe_read_handle, '-|:encoding(UTF-8)', 'cat', 'unicode.string.txt' || die;
my $unicode_string_open_pipe = <$open_pipe_read_handle>;
# print unicode to files
open my $hardcoded_handle, '>', 'unicode.string.hardcoded' || die;
print $hardcoded_handle 'Ж 会 र';
close $hardcoded_handle;
open my $variable_handle, '>', 'unicode.string.variable' || die;
print $variable_handle $unicode_string_variable;
close $variable_handle;
open my $argv_handle, '>', 'unicode.string.argv' || die;
print $argv_handle $unicode_string_argv;
close $argv_handle;
open my $backticks_handle, '>', 'unicode.string.backticks' || die;
print $backticks_handle $unicode_string_backticks;
close $backticks_handle;
open my $open_pipe_handle, '>', 'unicode.string.open_pipe' || die;
print $open_pipe_handle $unicode_string_open_pipe;
close $open_pipe_handle;
# print unicode to STDOUT
printf "%s: %s\n", 'hardcoded', 'Ж 会 र';
printf "%s: %s\n", 'variable ', $unicode_string_variable;
printf "%s: %s\n", 'argv ', $unicode_string_argv;
printf "%s: %s\n", 'backticks', $unicode_string_backticks;
printf "%s: %s\n", 'open_pipe', $unicode_string_open_pipe;
initscr;
# print unicode to Curses
addstring 0, 0, 'hardcoded: ' . 'Ж 会 र';
addstring 1, 0, 'variable : ' . $unicode_string_variable;
addstring 2, 0, 'argv : ' . $unicode_string_argv;
addstring 3, 0, 'backticks: ' . $unicode_string_backticks;
addstring 4, 0, 'open_pipe: ' . $unicode_string_open_pipe;
addstring 5, 0, 'Curses ' . Curses->VERSION . ", perl $^V" . ", OS: $^O";
getchar;
endwin;
бегать:
perl -CA curses-unicode.addstring.utf8,CA,encodingUTF8.pl 'Ж 会 र'
Вывод проклятий, частично рабочий, частично битый юникод::
hardcoded: Ж 会 र
variable : Ж 会 र
argv : Ж 会 र
backticks: Ð~V ä¼~Z र
open_pipe: Ж 会 र
Curses 1.43, perl v5.36.0, OS: openbsd
Выход STDOUT&STDERR, всерабочий юникод:
Wide character in print at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 12, <$open_pipe_read_handle> line 1.
Wide character in print at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 15, <$open_pipe_read_handle> line 1.
Wide character in print at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 18, <$open_pipe_read_handle> line 1.
Wide character in print at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 24, <$open_pipe_read_handle> line 1.
Wide character in printf at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 28, <$open_pipe_read_handle> line 1.
hardcoded: Ж 会 र
Wide character in printf at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 29, <$open_pipe_read_handle> line 1.
variable : Ж 会 र
Wide character in printf at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 30, <$open_pipe_read_handle> line 1.
argv : Ж 会 र
backticks: Ж 会 र
Wide character in printf at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line 32, <$open_pipe_read_handle> line 1.
open_pipe: Ж 会 र
Вывод файлов, всерабочий юникод:
cat unicode.string.*
Ж 会 रЖ 会 रЖ 会 रЖ 会 रЖ 会 रЖ 会 र
STDOUT и записывает в файлы во всех 3 случаях без каких-либо проблем, тогда как Curses мешает? Что особенного в Curses? Не является ли это какой-то ошибкой в Curses, учитывая, что с STDOUT и файлами все в порядке?use utf8 для юникода в исходнике;-CA для аргументов cli;:encoding(UTF-8) за openWide character in print at curses-unicode.addstring.utf8,CA,encodingUTF8.pl line ..., <$open_pipe_read_handle> line 1. на STDERR и как от них избавиться?




Вам нужна прагма use utf8;:
use utf8;
use Curses;
initscr;
addstring 0, 0, 'Ж 会 र';
addstring 1, 0, 'Curses ' . Curses->VERSION . ", perl $^V" . ", OS: $^O";
getch;
endwin;
Выход:
Ж 会 र
Curses 1.43, perl v5.34.0, OS: linux
См. Часто задаваемые вопросы о Perl Unicode. Почему работает версия addstr, наверное, дело везения (в моей системе корректно отображается только третий символ).
Если вы хотите обрабатывать аргументы командной строки из $ARGV как utf8, вам нужен другой подход. Один из способов — явный вызов Perl с флагом -C, установленным на A или 32 (это специальный параметр, который управляет кодировкой $ARGV) или, что то же самое, путем установки переменной среды PERL_UNICODE в терминале на A.
В качестве альтернативы вы можете перекодировать $ARGV из кода:
use Encode qw(decode_utf8);
@ARGV = map { decode_utf8($_, 1) } @ARGV;
В этом случае вам не нужен флаг командной строки.
Эта альтернатива также работает для замены обратных кавычек:
use Encode qw(decode_utf8);
my $unicode_string_backticks = decode_utf8(`cat unicode.string.txt`, 1);
Источник: https://www.perl.com/pub/2012/04/perlunicookbook-decode-argv-as-utf8.html/
Однако существует более простое решение, которое одновременно устанавливает utf8 для жестко закодированных строк, argv, файловых дескрипторов, printf, обратных кавычек и т. д., что является модулем utf8::all. При этом вам не нужны флаги командной строки или модуль Encode. Поскольку он нацелен на STDOUT, предупреждения о широких символах также разрешаются.
use utf8::all;
use Curses;
my $unicode_string_variable = 'Ж 会 र';
my $unicode_string_argv = $ARGV[0];
#my $unicode_string_backticks = decode_utf8(`cat unicode.string.txt`,1);
my $unicode_string_backticks = `cat unicode.string.txt`;
open my $open_pipe_read_handle, '-|:encoding(UTF-8)', 'cat', 'unicode.string.txt' || die;
my $unicode_string_open_pipe = <$open_pipe_read_handle>;
# print unicode to files
open my $hardcoded_handle, '>', 'unicode.string.hardcoded' || die;
print $hardcoded_handle 'Ж 会 र';
close $hardcoded_handle;
open my $variable_handle, '>', 'unicode.string.variable' || die;
print $variable_handle $unicode_string_variable;
close $variable_handle;
open my $argv_handle, '>', 'unicode.string.argv' || die;
print $argv_handle $unicode_string_argv;
close $argv_handle;
open my $backticks_handle, '>', 'unicode.string.backticks' || die;
print $backticks_handle $unicode_string_backticks;
close $backticks_handle;
open my $open_pipe_handle, '>', 'unicode.string.open_pipe' || die;
print $open_pipe_handle $unicode_string_open_pipe;
close $open_pipe_handle;
# print unicode to STDOUT
printf "%s: %s\n", 'hardcoded', 'Ж 会 र';
printf "%s: %s\n", 'variable ', $unicode_string_variable;
printf "%s: %s\n", 'argv ', $unicode_string_argv;
printf "%s: %s\n", 'backticks', $unicode_string_backticks;
printf "%s: %s\n", 'open_pipe', $unicode_string_open_pipe;
initscr;
# print unicode to Curses
addstring 0, 0, 'hardcoded: ' . 'Ж 会 र';
addstring 1, 0, 'variable : ' . $unicode_string_variable;
addstring 2, 0, 'argv : ' . $unicode_string_argv;
addstring 3, 0, 'backticks: ' . $unicode_string_backticks;
addstring 4, 0, 'open_pipe: ' . $unicode_string_open_pipe;
addstring 5, 0, 'Curses ' . Curses->VERSION . ", perl $^V" . ", OS: $^O";
getchar;
endwin;
Источник: https://blog.ostermiller.org/perl-wide-character-in-print/
Если по какой-либо причине вы не можете или не хотите устанавливать этот модуль, то use utf8; вместе с флагами командной строки -CSDA также решит все проблемы. Обратите внимание, что с этими флагами командной строки вы не должны использовать decode_utf8() в своем коде.
@uxer для этого использования perl -CA curses.unicode.pl 'Ж 会 र'.
Хорошо знать. Шаг вперед: мы получаем нашу юникодную строку через обратные кавычки или open. Последнее, кажется, нужно :encoding(UTF-8). Как исправить обратные кавычки? Зачем нужны 3 разных места — use utf8, -CA, :encoding(UTF-8) — чтобы включить один и тот же чертов юникод? Где единообразие? Почему это требуется только для Curses, а STDOUT и запись в файлы работают «из коробки»? Я также получаю ошибки Wide character in print... Я обновил вопрос
@uxer смотрите изменения для версии с обратными кавычками и единого решения для всех проблем.
Полу-да. Этот данный фрагмент теперь работает правильно, но вместо
addstring 0, 0, $ARGV[0];ставитеaddstring 0, 0, 'Ж 会 र';, потом вызываетеperl curses.unicode.pl 'Ж 会 र'и снова появляется мусор