Чтение команд из файла

alias rm.dup  'perl -ne '\''print unless $dup{$_}++'\'' \!* &'

Поскольку нельзя вставить одинарную кавычку в одинарные кавычки, один из способов — вырваться из одинарной кавычки, вставить буквальную кавычку, а затем перезапустить кавычки.

'perl -ne '\''print unless $dup{$_}++'\'' \!* &'
|---------|B |-----------------------|D |------|
     A                   C                  E

Другой способ:

alias rm.dup  'perl -ne "print unless "\$"dup{"\$"_}++" \!* &'
0
23.06.2019, 01:48
1 ответ

Оболочка анализирует конвейеры (и перенаправляет, и заключает в кавычки, и экранирует и... )перед раскрытием переменных, поэтому, если вы поместите конвейер (или перенаправление или... )в переменную, когда он расширен, уже слишком поздно для нормального функционирования; в этот момент это просто обычный аргумент команды. См. BashFAQ #50 :Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!

Решение :В этом случае я бы рекомендовал использовать eval. evalимеет очень плохую репутацию магнита для насекомых, потому что его легко использовать не по назначению опасным образом. По сути, его цель состоит в том, чтобы выполнять данные, как если бы они были синтаксисом и командами оболочки, и это означает, что грань между исполняемым кодом и инертными данными (, такими как имена файлов ), даже слабее, чем обычно. Но в этом случае данные, считанные из ZLD _Command _list.txt, должны обрабатываться как синтаксис и команды оболочки. Если в файле есть rm -R /, предполагается, что удалит всю файловую систему.

Тем не менее, вы все равно должны соблюдать правила цитирования. Это означает двойное -цитирование переменных, например eval "$variable1"вместо простого eval $variable1. Кроме того, я рекомендую использовать $()вместо обратных кавычек (, см. BashFAQ #82 ), но поскольку вы просто собираетесь echoполучить результат, почему бы просто не выполнить команду напрямую?

Другие возможные оптимизации :Вместо того, чтобы копировать значение $Commandв $variable1, просто используйте его напрямую. Вместо перенаправления вывода каждой команды по отдельности, почему бы не перенаправить вывод всего цикла?

Вот моя версия, со всем вышеперечисленным исправленным:

#!/bin/bash
while IFS=#, read -r Command_info1 Command; do
    echo "$Command_info1"
    eval "$Command"
done < /ZLD_Implement/ZLD_Command_list.txt > /ZLD_Implement/ZLD_Implement.txt

О, и вы хотите записывать вывод ошибок, а также стандартный вывод команд? Если это так, добавьте 2>&1после окончательного перенаправления.

1
28.01.2020, 02:40

Теги

Похожие вопросы