почему изменение с "на" влияет на поведение этой однострочной строки?

Почему простое включение однострочного текста с ' вместо " влияет на поведение кода? Первая строка кода дает то, что ожидается, а вторая строка кода дает (для меня!) Неожиданный результат, распечатывая неожиданную ссылку на массив.

$ echo "puke|1|2|3|puke2" | perl -lne 'chomp;@a=split(/\|/,$_);print $a[4];'
puke2
$ echo "puke|1|2|3|puke2" | perl -lne "chomp;@a=split(/\|/,$_);print $a[4];"

Это версия Perl:

$ perl -v

This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi

ARRAY(0x1f79b98)

person sail0r    schedule 11.05.2017    source источник
comment
Попробуйте: echo chomp; @ a = split (/ \ | /, $ _); print $ a [4] ;, Perl не задействован, и вы увидите, что вы передаете Perl во втором случае.   -  person martin clayton    schedule 12.05.2017
comment
@martinclayton Ницца. Одно дело - труба, о которой идет речь, влияет на $_, поэтому эта часть будет неточной. (Хотя в реальной проблеме, конечно, данные могут вообще не передаваться по конвейеру.)   -  person zdim    schedule 12.05.2017
comment
@martinclayton Неоднократно исполнять это забавно :)   -  person zdim    schedule 12.05.2017


Ответы (2)


С двойными кавычками вы позволяете оболочке сначала интерполировать переменные.

Как вы можете проверить, $_ и $a не установлены в подоболочке, разветвленной для канала родительской оболочкой. См. Комментарий к $_ ниже.

Таким образом, версия с двойными кавычками эффективно

echo "puke|1|2|3|puke2" | perl -lne 'chomp;@a=split(/\|/);print [4];'

что печатает ссылку на массив [4].


Комментарий о последствиях воздействия $_ на Bash. Спасибо Бородину за то, что подняли этот вопрос.

$_ - одна из немногих специальной оболочки. параметры в Bash. Он содержит последний аргумент предыдущей команды или путь к тому, что вызвало оболочку или команды (через переменную среды _). См. Ссылку для полного описания.

Однако здесь он интерпретируется в подоболочке, разветвленной для запуска первой команды perl. Судя по всему, это даже не установлено, как видно с

echo hi;  echo hi | echo $_

который печатает пустую строку (после первого hi). Причина может заключаться в том, что переменная среды _ просто не установлена ​​для подоболочки для канала, но я не понимаю, почему это так. Например,

echo hi; (echo $_)

печатает две строки с hi, хотя ( ) запускает подоболочку.

В любом случае $_ в данном конвейере не задано.

Часть split тогда split(/\|/), поэтому по умолчанию split(/\|/, $_) - нечего разделять. С добавлением -w это действительно выводит предупреждение об использовании неинициализированного $_.

Обратите внимание, что это поведение зависит от оболочки. tcsh вообще не запускает это с двойными кавычками. В ksh и zsh последняя часть конвейера выполняется в основной оболочке, а не в подоболочке, поэтому $_ присутствует.

person zdim    schedule 11.05.2017
comment
Фактически, $_ во многих оболочках является последним аргументом самой последней команды, но если бы он не был назначен, код Perl выглядел бы как split(/\|/,), который в любом случае имеет значение по умолчанию split(/\|/, $_). Настоящая проблема, как вы говорите, в том, что $a[4] сокращается до [4]. - person Borodin; 12.05.2017
comment
@Borodin Я думаю, что он оказывается пустым из-за трубы. (Так оно и было в моих кратких тестах.) Тем не менее, я должен и объясню это лучше, большое вам спасибо. - person zdim; 12.05.2017

Это актуальная тема оболочки, а не Perl.

В ракушке:

Одиночные кавычки сохраняют буквальное значение всех содержащихся в них символов, включая $ и обратную косую черту. Однако в двойных кавычках символы $, обратная косая черта и обратная косая черта имеют особое значение.

Например:

'\"' оценивается как \"

в то время как

"\'" оценивается как '

потому что с двойными кавычками обратная косая черта получает особое значение как escape-символ.

person MBurnham    schedule 11.05.2017