Перл, записывающий в "файл памяти", выполняет трюки с совпадением рисунков
Когда я запускаю этот код, я получаю "нет":
my $memory_file;
my $fh;
open ($fh, '>', \$memory_file);
print $fh "abc";
if( $memory_file =~ m/^.*$/ )
{ print "yes\n" }
else
{ print "no\n" }
Если я распечатаю $memory_file
, содержимое действительно "abc"
.
Если изменить шаблон на .*
(нет ^
или $
), он будет работать как ожидалось.
Если я поместил строку $memory_file = "abc"
перед совпадением, я получаю "да" распечатан (как первоначально ожидалось).
Что здесь происходит?
(Это perl 5.14.1)
Обновление: Еще некоторое обсуждение PerlMonks. Это похоже на ошибку, я запишу ее.
Обновление 2: Прекрасные разработчики Perl исправили эту ошибку: https://rt.perl.org/rt3//Public/Bug/Display.html?id=108398
Ответы
Ответ 1
Это конец символа линии, который перепутал вещи. Пока работает регулярное задание:
my $str = "abc";
print "Works" if $str =~ /^.*$/;
... кода в вопросе нет. Это регулярное выражение должно соответствовать любой строке, так как оно также соответствует пустой строке. Даже значения undefined будут совпадать (хотя это вызовет предупреждение). Кроме того, ^.*
соответствует.
Единственное разумное объяснение заключается в том, что по какой-либо причине какая-либо проверка выполняется для соответствия концу строки, она не находит ее. Конец строки отсутствует.
Любопытно, что замена $
на \z
работает. Но не \z
.
Добавление новой строки также работает. Который имел бы смысл иметь смысл, поскольку добавление новой строки подразумевало бы, что конец строки также добавляется в смысле не-многострочного регулярного выражения.
Я не знаю внутренней работы, почему это происходит, но я подозреваю, что при использовании этой конкретной формы "назначения" маркер конца строки никогда не помещается в строку. Это своего рода "сырое" задание, которое путает проверку конца строки в регулярном выражении.
Это похоже на ошибку. Возможно, эта особенность не была должным образом сохранена.
Ответ 2
Я думаю, что проблема - это символ новой строки и $
. Он проверяет строку после строки новой строки, а ваша строка не имеет значения.
ИЗМЕНИТЬ
См. подробное объяснение проблемы в других ответах, потому что моя была неправильной. Но я дам два варианта для его решения:
- Напишите "abc\n" в ваш файл и установите флажок
$
- Проверьте конец строки с помощью
\z
.
Ответ 3
просто используйте вспомогательную переменную.
#$| = 1; # AutoFlush
my $memory_file;
open ( my $fh, '>>', \$memory_file) or die $!;
print $fh "abc";
my $buff = $memory_file;
if( $buff =~ m/^abc$/ ){ # or m/^.*$/
print "yes\n";
}else{
print "no\n";
}
Ответ 4
Ну, мой первый инстинкт - сказать, что файлы в памяти не действуют так же, как физические файлы. Попробуйте изменить print $fh "abc";
на print $fh "abc\n";
, чтобы убедиться, что ваш вход "становится" линией.
Мой другой инстинкт заключается в том, что ваш файл на самом деле не написан до того, как вы его прочитали. Сбросьте буфер с помощью $|++;
Итак, попробуйте:
my $memory_file;
my $fh;
open ($fh, '>', \$memory_file);
print $fh "abc";
$|++;
if( $memory_file =~ m/^.*$/ )
{ print "yes\n" }
else
{ print "no\n" }