Bash: чтение строки из файла с подстановкой переменных

У меня странная ситуация: у меня есть команда, хранящаяся в файле, и этот файл содержит ссылки на переменные.

Я могу нормально прочитать файл, но у меня возникли проблемы с работой расширения переменных.

В качестве минимального рабочего примера, вот файл, содержащий команду с переменной в качестве примера:

команда.в

ls $DIR

простой.sh

#!/bin/bash

MYVAR=$(<command.in)
DIR = "/tmp"

$MYVAR

Ожидаемые результаты

Мои ожидаемые результаты заключаются в том, что он напечатает содержимое /tmp.

Что я пробовал

Я пробовал переместить задание DIR выше задания MYVAR в simple.sh и изменить $DIR в command.in на ${DIR} и $(DIR)

Вам нужно будет использовать eval для оценки строки до ls <content of $DIR>, прежде чем пытаться выполнить команду. Я бы рекомендовал не определять command.in таким образом; просто создайте скрипт, который принимает аргумент (ls "$1"), а затем выполните command.in "$DIR".

chepner 08.07.2024 16:01

Я думаю тебе нужно eval

Mark Setchell 08.07.2024 16:02

@chepner На самом деле я делаю какие-то странные вещи, где я хочу вызвать скрипт после того, как все изображения сгенерированы, но среда еще не разрушена. Я мог бы жестко запрограммировать содержимое сценария в рецепте, но это своего рода антишаблон на тот случай, если сценарий необходимо изменить или мне нужно поделиться этим с другой командой, с которой я работаю. Я все еще мог бы сделать $1 и так далее, но для простоты использования я параметризовал скрипт.

SailorCire 08.07.2024 16:38

Примечание к стилю: не следует использовать ВЕРХНИЙ РЕГИСТР для переменных Bash. По соглашению верхний регистр зарезервирован для использования в оболочке, например PATH. Пользовательские переменные должны быть в нижнем регистре...

dawg 08.07.2024 16:44

То, что вы сейчас делаете, еще больше противоречит шаблону. command.in на данный момент не параметризован; это то, что я предлагаю вам сделать.

chepner 08.07.2024 16:53

@chepner Я имею в виду, что у меня действительно параметризовано содержимое «реального» содержимого. Он использует getopts и все такое. Чтобы не сделать вопрос слишком конкретным, я не увидел преимуществ содержания. в том, чтобы быть myprog --dir $DIR против ls $DIR. Если вы считаете, что это поможет будущим людям в поиске, я с радостью обновлю его.

SailorCire 09.07.2024 14:57

Команда, выполняемая command.in, не имеет значения. Дело в том, что вам следует выполнять скрипт с аргументом (command.in "$DIR", который выполняется myprog --dir "$1" с расширением $1 до значения $DIR) вместо того, чтобы пытаться динамически расширить жестко запрограммированное расширение параметра в содержимом command.in.

chepner 09.07.2024 16:32

@SailorCire Возможно, вы правы в своем конкретном случае. Мы с Чепнером комментируем не это. Имейте в виду, что это место предназначено для людей с разным уровнем программирования. Научный, современный, многословный или даже педантичный синтаксис кода будет полезен большему количеству людей, чем что-то, что срезает углы, и потенциально может привить плохую практику новичкам, у которых нет опыта и знаний, чтобы знать, является ли срезание углов для их конкретного варианта использования правильным выбором. .

Léa Gris 10.07.2024 09:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
86
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

$(<command.in) разыменовывает переменную. Вы можете увидеть, что происходит, если поставите echo в скрипт:

#!/bin/bash
DIR = "/tmp"
MYVAR=$(<command.in)
echo $MYVAR
$MYVAR

который дает:

bash simple.sh
ls $DIR
ls: cannot access '$DIR': No such file or directory

Когда вы это сделаете $MYVAR, переменная будет расширена один раз. Итак, он производит ls $DIR и вот что выполняется. С помощью eval вы можете принудительно установить другой уровень расширения переменных:

#!/bin/bash
DIR = "/tmp"
MYVAR=$(<command.in)
echo "$MYVAR"
eval "$MYVAR"

Идеальный! использование eval решило проблему. Спасибо! Большинство примеров eval, которые я видел, были чем-то вроде eval $var, и я не знаю разницы между этим и простым вызовом $var напрямую.

SailorCire 08.07.2024 16:34

Вам все равно нужно взять в кавычки переменные echo "$MYVAR" и eval "$MYVAR".

Léa Gris 08.07.2024 17:29

потребность немного преувеличена; работает без кавычек. Но я согласен: цитировать надо было.

Ljm Dullaart 08.07.2024 17:37

@LjmDullaart, ... это "работает" без кавычек. То есть, похоже, что это работает до тех пор, пока вы не попробуете интересный случай, а затем удивительным образом терпит неудачу.

Charles Duffy 08.07.2024 17:42

Например, сравните eval "$code" и eval $code с code=$'printf \' * %s\\n\' *'. И последнее, конечно, намного хуже, чем просто плохой результат, если при запуске в текущем рабочем каталоге есть файл с $(rm -rf ~) как часть его имени.

Charles Duffy 08.07.2024 18:36

Просто измените command.in на

ls "$1"

затем выполните его как обычный скрипт (поскольку теперь это обычный параметризованный скрипт).

#!/bin/bash

DIR = "/tmp"

bash command.in "$DIR"

Другие вопросы по теме