2016-02-22 2 views
0

Предположим, у меня есть файл path.txt, содержащий текст $HOME/filedump/ на одной строке. Как я могу затем прочитать содержимое path.txt в переменной, в то время как Bash анализирует содержимое?Получение Bash для анализа переменных из ввода файла

Вот пример того, что я пытаюсь сделать:

#!/bin/bash 
targetfile="path.txt" 

target=$([[ -f $targetfile ]] && echo $(< $targetfile) || echo "Not set") 
echo $target 

Желаемый результат: /home/joe/filedump/

Фактический выход: $HOME/filedump/

Я попытался с помощью cat вместо <, обертывая его в кавычки и многое другое. Кажется, мне ничего не кажется.

Уверен, что мне не хватает чего-то очевидного, и, вероятно, есть простая встроенная команда. Все, что я могу найти на Google, это страницы о чтении переменных из ini/config-файлов или разбиении одной строки на несколько переменных.

+0

посмотрите на 'eval' в man bash. –

ответ

1

Если вы хотите, чтобы оценить содержание path.txt и назначить, что target, а затем использовать:

target=$(eval echo $(<path.txt)) 

, например:

$ target=$(eval echo $(<path.txt)); echo "$target" 
/home/david/filedump/ 
+0

Ага! После вашего комментария я попробовал около 10 различных способов запуска eval, но не этого. Только то, что доктор заказал, спасибо! –

+0

В случае, если кто-либо использует сокращенный синтаксис в OP, мне пришлось добавить дополнительное 'echo', resuling в' '' target = $ ([[-f $ targetfile]] && echo $ (eval echo $ (<$) targetfile)) || ...) '' '. –

+1

Конечно, рад, что я мог бы помочь. Ключ с 'eval' заключается в понимании того, что он будет пытаться и делать то, что он оценивает (например, как будто вы вводите результат в виде команды оболочки). Вы не хотите выполнять результат, вы хотите присвоить результат переменной. Чтобы присвоить значение, вы хотите, чтобы 'eval' выводил результат. 'echo' заставляет' eval' оценивать все выражение 'echo $ HOME/filedump /'. (это то, что вы * можете * назначить) –

0

Это не обязательно может удовлетворить ваши потребности (в зависимости от контекста кода вы предоставили), но следующие работал для меня:

targetfile="path.txt" 
target=$(cat $targetfile) 
echo $target 
+0

Это доходит до захвата содержимого файла, но на самом деле он не конвертирует '$ PATH' в'/home/joe', как вы ожидали. В эхе будет отображаться только исходный текст из файла path.txt. –

+0

Он лично преобразован в путь к файлу для меня - не уверен, что что-то еще в моей установке (zsh?) Делает это уже. Быстрая запись на терминале - https://asciinema.org/a/1o5gnn6k6v7phvz9cowtfmdgx Убрав использование скрипта bash, cat path.txt сам по себе выводит полный путь как в bash, так и в zsh для меня. Вероятно, мне следовало бы проверить, что дает мне мой код. – mediantis

+0

Ах. Это что-то еще - запуск кода, который вы предоставили, - печатает путь для меня. Вы используете что-то другое, кроме bash или zsh, случайно? – mediantis

0

Вот более безопасная альтернатива, чем eval. В общем, вы не должны использовать конфигурационные файлы, которые требуют bash для оценки их содержимого; что просто открывает угрозу безопасности в вашем скрипте. Вместо этого обнаруживает, если есть что-то, что требует оценки, и обрабатывать его явно. Например,

IFS= read -r path < path.txt 
if [[ $path =~ '$HOME' ]]; then 
    target=$HOME/${path#\$HOME} 
    # more generally, target=${path/\$HOME/$HOME}, but 
    # when does $HOME ever appear in the *middle* of a path? 
else 
    target=$path 
fi 

Это требует, чтобы вы знали заранее, какие переменные могут появиться в path.txt, но это хорошая вещь. Вы не должны оценивать неизвестный код.

Обратите внимание, что вы можете использовать любой заполнитель вместо переменной в этом случае; %h/filedump могут быть обнаружены и обработаны так же легко, как $HOME/filedump, без предположения, что содержимое может или должно быть оценено как код оболочки.

Смежные вопросы