Почему вложение этой команды awk с помощью eval дает другой результат, чем ее выполнение? - PullRequest
0 голосов
/ 22 января 2019

У меня есть этот скрипт, который предназначен для назначения переменных командам, которые собирают информацию о системе, а затем возвращают их обратно.Это работает очень хорошо для первых нескольких команд, но последняя продолжает возвращать значение без "PRETTY_NAME =", исключенного из вывода.

Есть ли какая-то проблема с этим, которую я не вижу?

Я пытался использовать grep для отделения awk:

grep PRETTY_NAME /etc/*-release | awk -F '=' '{print $2}'

Использование экранированных кавычек:

awk -F \"=\" '/PRETTY_NAME/ {print $2}' /etc/*-release

Весь блок(немного отредактировано для актуальности)

declare -A CMDS=(
   [primaryMacAddress]="cat /sys/class/net/$(ip route show default | awk '/default/ {print $5}')/address" 
   [primaryIpAddress]="hostname --ip-address"
   [hostname]="hostname"
   [osType]="awk -F '=' '/PRETTY_NAME/ {print $2}' /etc/*-release"
   )

#This bit is actually nested in another function
for kpair in "${!CMDS[@]}" do
   echo "$kpair=\"$( eval ${CMDS[$kpair]} )\""
done 

Результаты при запуске из .sh файла:

osType = "PRETTY_NAME =" Red Hat Enterprise Linux Server 7.4 (Maipo) ""

ожидается:

osType = "" Red Hat Enterprise Linux Server 7.4 (Maipo) ""

Когда эта команда запускается самаКажется, он работает как задумано:

$ awk -F '=' '/ PRETTY_NAME / {print $ 2}' / etc / * - release

"КрасныйHat Enterprise Linux Server 7.4 (Maipo) "

1 Ответ

0 голосов
/ 23 января 2019

Поскольку ваша команда Awk указана в двойных кавычках, внутренние знаки доллара подлежат особой обработке: $2 рассматривается как замена параметров вашей оболочкой, и поэтому элемент массива не хранит текст $2а скорее его расширение.Интерпретатор Awk никогда не видит синтаксис $2.

Однако у вас есть вторая проблема в вашем диспетчере команд.Ваша команда eval не предотвращает разбиение слов:

eval ${CMDS[$kpair]}

Вы хотите это:

eval "${CMDS[$kpair]}"

без кавычек, ваша команда произвольно нарезается на поля в пустом пространстве.Затем eval объединяет части вместе, используя один пробел между ними, и оценивает полученный синтаксис.Разницу можно продемонстрировать на следующем примере:

$ cmd="awk '/foo/ { print \$1\"    \"\$2 }'"
$ echo 'foo a' | eval $cmd
foo a
$ echo 'foo a' | eval "$cmd"
foo    a

Мы можем просто использовать echo, чтобы понять проблему:

$ echo $cmd
awk '/foo/ { print $1" "$2 }'
$ echo "$cmd"
awk '/foo/ { print $1"    "$2 }'

Подстановка $cmd и последующее словорасщепление выполняется независимо от любого синтаксиса оболочки, который содержит `cmd.Мы можем видеть такие фрагменты, как это:

$ for x in $cmd ; do echo "<$x>" ; done
<awk>
<'/foo/>
<{>
<print>
<$1">
<"$2>
<}'>

Когда мы выполняем eval $cmd, вышеуказанные фрагменты генерируются и повторно комбинируются с помощью eval и оцениваются.Излишне говорить, что вы не хотите, чтобы ваш командный синтаксис был нарезан и повторно объединен таким образом;кто знает, какого рода скрытая ошибка возникнет.Это может быть хорошо для команд, которые у вас сейчас есть, но как общий механизм диспетчеризации команд, он имеет недостатки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...