Перл, записывающий в "файл памяти", выполняет трюки с совпадением рисунков

Когда я запускаю этот код, я получаю "нет":

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" }