Краткий ответ на ваш вопрос заключается в том, что $filename
интерполируется в вашем первом примере, а во втором - нет. Почему ты спрашиваешь? О, парень. Пристегнитесь для ухабистой езды.
Во-первых, поймите, для чего предназначена нотация ${...}
. Есть две причины для его использования: первая — просто отличить имя переменной от окружающего текста; другой - разыменовать значение, возвращаемое БЛОКОМ (кода).
Если содержимое скобок — это просто пустое слово (с возможными пробелами вокруг него), то это просто имя переменной. Таким образом, строка "$foo"
, строка "${foo}"
и строка "${ foo }"
дают один и тот же результат. Это удобно, если вам нужно добавить текст непосредственно после переменной в строке: вместо $foo.'bar'
вы можете сказать "${foo}bar"
. Обозначения работают и вне интерполирующих строк: вы можете сказать ${foo} = 'bar'
, если хотите.
Но это не то, что делает ваш код. О, нет. Вы нацеливаете двуствольное ружье символического разыменования прямо себе под ноги. Вы оцениваете содержимое скобок как код и используете результат как ссылку на переменную. Вы делаете это вдвойне запутанным, помещая все это в интерполирующую строку. Не будем углубляться в концепцию разыменования, если это необходимо, так как это не главный вопрос здесь. Ключевым моментом является то, что материал в фигурных скобках эффективно оценивается, если это не голое слово.
Теперь поймите, что когда Perl достигает нотации "${" внутри вашей интерполируемой строки, он должен принять решение о том, что он здесь интерполирует: обычное имя переменной или код. Без интерполяции чего-либо еще выполняется поиск соответствующей закрывающей скобки. Если подстрока, заключенная в эти скобки, не выглядит голым словом, то она будет оценена. Вам по-прежнему нужно избегать двойных кавычек в этой области, потому что любая неэкранированная двойная кавычка будет считаться последним разделителем для внешней строки, подмножеством которой является это, а оставшаяся часть вашего «блока» будет вне строки.
Имея это в виду, мы видим, что ваш первый пример оценивается как "_<$filename"
, тогда как ваш второй пример оценивается как '_<$filename'
. В этом разница между интерполирующей строкой и нет: в первой $filename
заменено на что-то, а во второй строго буквальная.
В обоих случаях строка используется для выполнения символического разыменования глобальной скалярной переменной с ужасным именем, и вам будет стыдно, если вы действительно ее определили. Чем меньше об этом сказано, тем лучше.
Если вы думаете, что я шучу о том, что содержимое фигурных скобок эффективно оценивается, попробуйте этот код.
print "This, ${die qq(oops!\n)}, and this.\n";
Конечно, ключевое различие между подобным кодом в строке и собственно eval()
заключается в том, что eval()
перехватит исключение и установит $@. Это не так: он просто умирает, как в обычном блоке кода.
Это порождает один из скрытых приемов Perl. Вы не можете интерполировать вызов метода, например $foo->bar
, но вы можете разыменовать ссылку на содержащий его массив, например.
print "@{[$foo->bar]}\n";
Подводя итог, ради Бога, пожалуйста, не пишите такой код.
person
TFBW
schedule
23.05.2019
"${ \"_<$filename\" }"
анализируется дважды. Если вы используете одинарные кавычки внутри, он не будет интерполировать$filename
(поскольку одинарные кавычки не интерполируются)? - person Håkon Hægland   schedule 23.05.2019