ограничить stdout скоростью вывода на терминал [дублировать]

"Я хочу, чтобы пользователям не приходилось указывать части пути, если для этого существуют переменные (например, $ HOME для домашнего каталога). "

Это можно сделать без eval :

$ s='$HOME/.config'
$ s="${s//\$HOME/$HOME}"
$ echo "$s"
/home/john1024/.config

Это имеет некоторые ограничения. Во-первых, если и HOMES, и HOME являются именами переменных, которые вы хотите подставить, то, чтобы избежать ложных совпадений, HOMES необходимо подставить перед HOME.

Применение замен для всех экспортируемых переменных

Использование bash:

while IFS== read -r name val
do
   s="${s//\$$name/$val}"
done < <(printenv)

Например:

$ export A=alpha; export B=beta
$ s='$HOME/$A/$B'
$ while IFS== read -r name val; do s="${s//\$$name/$val}"; done < <(printenv)
$ echo "$s"
/home/john1024/alpha/beta

Поскольку этот подход не сортирует имена переменных по длине, возникает проблема перекрытия переменных, упомянутая выше.

Мы можем исправить это, отсортировав имена переменных по длине:

while IFS== read -r n name val
do
   s="${s//\$$name/$val}"
done < <(printenv | awk '/^[^ \t]/{key=$0; sub(/=.*/,"",key); printf "%s=%s\n",length(key),$0}' | sort -rnt=)

Если пользователь вводит имя переменной, которое не существует, но начальные символы соответствуют некоторому более короткому имени, более короткое имя будет заменены. Если это имеет значение, мы можем избежать этого, потребовав от пользователя использовать скобки для этих переменных с помощью этого кода:

while IFS== read -r n name val
do
   s="${s//\$\{$name\}/$val}"
done < <(printenv | awk '/^[^ \t]/{key=$0; sub(/=.*/,"",key); printf "%s=%s\n",length(key),$0}' | sort -rnt=)

В качестве примера:

$ s='${HOME}/${A}/${B}'
$ while IFS== read -r n name val; do s="${s//\$\{$name\}/$val}"; done < <(printenv | awk '/^[^ \t]/{key=$0; sub(/=.*/,"",key); printf "%s=%s\n",length(key),$0}' | sort -rnt=)
$ echo "$s"
/home/john1024/alpha/beta
3
13.04.2017, 15:36
0 ответов

Теги

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