Следующий простой скрипт (в основном) slurps на своем входе, разделяет его в соответствии с регулярным выражением, заменяет все строки новой строки в каждом элементе результирующего списка и печатает из модифицированных элементов один за другим:Ошибка Unicode только при запуске кода с флагом -n в командной строке
# demo.pl
use strict;
use utf8;
use open qw(:std :utf8);
use warnings qw(FATAL utf8);
BEGIN { $/ = $\ = undef; }
while (<>) {
s/\n\z//;
s/\n/\\n/g, print "$_\n" for split /\n(?=[^\W\d]\w*=)/;
}
Когда дан входной файл (INPUTFILE
) со следующим (UTF-8 кодировкой) содержанием в качестве аргумента
A=42
ΦΡΩΒΩΖΖ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=
foo
345bar=nope
baz
=whatever=
X_Y_Z=quux
... он печатает желаемый выход, а именно:
% perl demo.pl INPUTFILE
A=42
ΦΡΩΒΩΖΖ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=\nfoo\n345bar=nope\nbaz\n =whatever=
X_Y_Z=quux
В отличие от этого, следующие практически идентичны CLI однострочник
% perl -ne 'use strict; use utf8; use open qw(:std :utf8); use warnings qw(FATAL utf8); BEGIN { $/ = $\ = undef; } s/\n\z//; s/\n/\\n/g, print "$_\n" for split /\n(?=[^\W\d]\w*=)/;' INPUTFILE
... производит следующие действия для того же входного файла
A=42\nΦΡΩÎΩÎÎ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=\nfoo\n345bar=nope\nbaz\n =whatever=
X_Y_Z=quux
Там являются (видимо) две проблемы здесь :
- регулярное выражение не может отделить первый и второй элементы;
- вывод содержит неразборчивую подстроку.
(я надеюсь, что обе эти проблемы будут иметь те же основные причины.)
Единственное различие между «в-файл сценария» (demo.pl
) и CLI однострочника является то, что бывший явно обертывает тело скрипта while (<>) { ... }
, тогда как для последнего флаг -n
заставляет эту оболочку вставляться автоматически.
Q: Как следует один вкладыш выше быть модифицирована таким образом, что она производит желаемый результат с -n
флагом?
Кстати, не удивительно, что точной командной строки эквивалент demo.pl
(без -n
флага), а именно
% perl -e 'use strict; use utf8; use open qw(:std :utf8); use warnings qw(FATAL utf8); BEGIN { $/ = $\ = undef; } while (<>) { s/\n\z//; s/\n/\\n/g, print "$_\n" for split /\n(?=[^\W\d]\w*=)/; }' INPUTFILE
также производит желаемый результат.
Таким образом, проблема, независимо от того, что это такое, имеет какое-то отношение к флагом -n
.
FWIW:
% perl -v | head -2
This is perl 5, version 20, subversion 2 (v5.20.2) built for x86_64-linux-gnu-thread-multi
EDIT: Еще один ключ: если вход неисправного однострочника пропускают через STDIN
, а не в качестве имени файла в @ARGV
(например,заменить INPUTFILE
с < INPUTFILE
), то он производит желаемый результат полностью разборчиво, хотя все еще некорректной, выход:
A=42\nΦΡΩΒΩΖΖ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=\nfoo\n345bar=nope\nbaz\n =whatever=
X_Y_Z=quux
Мой текущий догадаться, что use open qw(:std :utf8)
не покрывает входной поток, который <>
считывает с момента, когда вход передается как имя файла в @ARGV
.
Это сбивает с толку. Я понял, что 'use ...' подразумевает' BEGIN {...} '. Я думал, это означало, что это произойдет, когда какой-либо из остальной части кода будет обработан ... – kjo
Спасибо. FWIW, версия, которую вы показываете только с помощью '-Ci' (в отличие от' -CiO'), терпит неудачу с вводом, данным в вопросе, из-за 'использования предупреждений qw (FATAL utf8)' вместе с наличием широких символов в выход. Избавление от 'использования предупреждений qw (FATAL utf8)' позволяет программе закончить, но все же предупреждение печатается. Нижняя строка: она должна быть '-CiO', а не' -Ci'. – kjo
'use' немного волшебный некоторое время. Хороший вопрос об предупреждениях - теперь редактируется. –