Как я могу избежать двойных кавычек в системной команде в этом perl oneliner? - PullRequest
2 голосов
/ 28 марта 2019

Для моего назидания я хотел бы узнать, как избежать кавычек в команде system в следующем perl oneliner:

$ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");'

без использования escape-последовательности \", как показано здесь: https://stackoverflow.com/a/1250279/3367247

(Очевидно, что эта команда не делает ничего полезного; она просто печатает имена файлов, в которых есть пробелы. Но она служит для краткого объяснения моей проблемы.)

Я попробовал следующее (извините за изображения, но я нашел, что подсвечивание легче всего расшифровать в кавычках):

  1. системная команда с двойными кавычками: system("echo "$_"") enter image description here

код: $ ls -p | grep -v / | perl -lane 'system("echo ''"''$_''"''");'

  1. системная команда с одинарными кавычками: system('echo "$_"') enter image description here

Код: $ ls -p | grep -v / | perl -lane 'system('"'"'echo "$_"'"'"');'

Ни одна из этих работ. Есть ли способ сделать это способом связанного ответа?

EDIT: мне нужны двойные кавычки вокруг $_ в команде echo, потому что строка в $_ содержит круглых скобок , а не потому, что она содержит пробелы, как я изначально думал.

Ответы [ 2 ]

1 голос
/ 29 марта 2019

Я хотел бы опубликовать некоторые идеи, которые я почерпнул из полезных комментариев и принятого ответа (спасибо всем!).В исходной команде, которую я поставил: $ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");' есть два интерпретатора: bash и perl, вступающие в игру:

  1. Исходная команда, интерпретируемая bash,ничего не трогает в (единственной паре) одинарных кавычек (то есть всего после -lane) и передает его без изменений в качестве скрипта в perl.

  2. Затем интерпретатор Perl обрабатываетэтот скрипт, который состоит из одной команды system.Именно интерпретатор perl отвечает за генерацию окончательной командной строки echo, которая отбрасывается обратно в bash для интерпретации.Эта последняя команда bash должна генерироваться динамически из $_.Есть два способа сделать это:

    (a) Использовать системную команду с двойными кавычками, чтобы интерполировать $_ [то есть system("echo $_")] Но обратите внимание, что отображаемая строка должна иметь "вокруг него, потому что он может содержать скобки.Таким образом, нам нужно perl для генерации в этой окончательной bash командной строке, буквально " s, вокруг $_ (которая будет расширена за счет внешнего "s, до отправки в bash).Теперь есть два способа выполнить this :

    (ai). Избегайте ", используя \ для выдачи буквенных кавычек: "echo \"$_\""

    (a-ii) Используйте оператор qq, который понижает специальный статус, присваиваемый " с внутри строки perl, и который затем может использоваться как обычные символы: qq(echo "$_").

    (b) -ИЛИ - другой способ создания окончательной команды bash - использовать одинарные кавычки в команде system, как предложил @ Håkon в своем ответе: system('echo ' . $_).Но нам все еще нужны кавычки около $_, как обсуждалось ранее, поэтому нам нужно изменить это на: system('echo "' . $_ . '"').Теперь задача сводится к выяснению экранирования одинарными кавычками в bash, чтобы убедиться, что Perl видит эту строку.

Окончательные формы команды perl:

2-ai: perl -lane 'system("echo \"$_\"");'

2-a-ii: perl -lane 'system(qq/echo "$_"/);'

И наконец:

2-b: perl -lane 'system('"'"'echo "'"'"'.$_.'"'"'"'"'"');'

Это извращение' s и " s - это то, что я намеревался достичь, поэтому МИССИЯ ВЫПОЛНЕНА!: D

От редакции. Из практической точки зрения удобства использования форма qq кажется наиболее подходящей для простого вставления окончательной, желаемой команды bash в вызов perl system (и затем вы можете просто заменить имена файлов).с $_).

0 голосов
/ 28 марта 2019

Я бы хотел узнать, как экранировать кавычки внутри системной команды в следующий perl oneliner:

$ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");'

без использования escape-последовательности, как показано здесь: [...]

Эти примеры предназначены для экранирования одинарных кавычек, ваш пример использует double quotes \"$_\". В Bash все в одинарных кавычках воспринимается буквально (кроме самой одинарной кавычки), то же самое нельзя сказать в двойных кавычках. Например, $ в двойных кавычках не является литералом $, но указывает на то, что должно следовать расширение переменной.

Теперь в вашем распоряжении три уровня интерпретации цитат.

  • Сначала внешняя оболочка (командная строка):

    perl -lane 'system("echo \"$_\"");'
    
  • Тогда интерпретатор Perl:

    system("echo \"$_\");
    
  • Затем вторая оболочка (здесь используется Bash):

    echo "xxx"
    

где xxx - расширение $_ в скрипте perl

Ваша команда не содержит внутренних одинарных кавычек, поэтому нет необходимости использовать конструкции цитирования Bash для экранирования одинарных кавычек, например

It's fine  -> 'It'"'"'s fine'

или

It's fine  -> 'It'\''s fine'

Далее, вам нужно экранировать двойные кавычки в скрипте perl

system("echo \"$_\"")

поскольку они заключены в двойные кавычки, вы можете удалить их поскольку echo здесь не нужны двойные кавычки:

system("echo $_")

будет работать нормально, или вы можете сделать, как предложено в комментариях:

system(qq/echo "$_"/)

или используйте форму LIST system с более чем одним аргументом

system("/bin/echo", $_)

Однако, если вы хотите использовать одинарные кавычки, например:

system('echo ' . $_)

вам нужно вызвать экранирование одинарной кавычки оболочки:

'system('"'"'echo ''"' . $_)'

или (используя двойные кавычки):

"system('echo ' . "'$'"_)"
...