Вот выдержка из моего ответа на сценарий оболочки: проверьте имя каталога и преобразуйте его в строчные буквы , в котором я демонстрирую не только, как решить эту проблему с помощью самых базовых утилит, определенных POSIX, но и адрес как очень просто сохранить результаты функции в возвращаемой переменной ...
... Ну, как видите, с некоторой помощью я нашел довольно простое и очень мощное решение:
Я могу передать функции своего рода переменную мессенджера и разыменовать любое явное использование имени $1
аргумента результирующей функции с eval
при необходимости, и, по завершении подпрограммы функции, я использую eval
и трюк с обратными слэшами, чтобы присвоить моей переменной-посланнику желаемое значение, даже не зная ее имени.
В полном раскрытии, ... [я нашел переменную часть посланника этого] и в трюки Рича , и я также извлек соответствующую часть его страницы ниже выдержки из моего собственного ответа.
...
ВЫПИСКА:
...
Хотя это и не строго POSIX, realpath является базовым приложением GNU с 2012 года . Полное раскрытие: никогда не слышал об этом до того, как я заметил это в info coreutils
TOC и сразу подумал о [связанном] вопросе, но использование следующей функции, как продемонстрировано, должно надежно, (скоро МОЖНО?), И, я надеюсь, эффективно
предоставить вызывающему абоненту абсолютно источник $0
:
% _abs_0() {
> o1="${1%%/*}"; ${o1:="${1}"}; ${o1:=`realpath -s "${1}"`}; eval "$1=\${o1}";
> }
% _abs_0 ${abs0:="${0}"} ; printf %s\\n "${abs0}"
/no/more/dots/in/your/path2.sh
РЕДАКТИРОВАТЬ: Возможно, стоит подчеркнуть, что это решение использует расширение параметра POSIX , чтобы сначала проверить, нужно ли вообще расширять и разрешать путь, прежде чем пытаться сделать это. Это должно вернуть абсолютно источник $0
через переменную мессенджера (с заметным исключением, что он сохранит symlinks
) как эффективно , как я мог себе представить это может быть сделано независимо от того, является ли путь уже абсолютным.
...
( незначительное редактирование : перед тем, как найти в документах realpath
, я по крайней мере урезал свою версию [нижеприведенной версии], чтобы она не зависела от поля времени [как это происходит в первой команде ps
, но, честное предупреждение, после тестирования некоторых я менее убежден, ps
полностью надежен в своей способности расширения пути команд )
С другой стороны, вы можете сделать это:
ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"
eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"
...
А из трюки Рича :
...
Возвращение строк из функции оболочки
Как видно из вышеприведенной ловушки подстановки команд, stdout не является хорошим способом для функций оболочки возвращать строки вызывающей стороне, если выходные данные не в формате, в котором конечные символы новой строки незначительны. Конечно, такая практика неприемлема для функций, предназначенных для работы с произвольными строками. Итак, что можно сделать?
Попробуйте это:
func () {
body here
eval "$1=\${foo}"
}
Конечно, ${foo}
можно заменить любым видом замены. Ключевой трюк здесь - это оценка линии и использование экранирования. “$1”
раскрывается, когда аргумент для eval создается основным анализатором команд. Но “${foo}”
на этом этапе не раскрывается, потому что “$”
указан в кавычках. Вместо этого он расширяется, когда eval оценивает свой аргумент. Если неясно, почему это важно, подумайте о том, как будет плохо:
foo='hello ; rm -rf /'
dest=bar
eval "$dest=$foo"
Но, конечно, следующая версия совершенно безопасна:
foo='hello ; rm -rf /'
dest=bar
eval "$dest=\$foo"
Обратите внимание, что в исходном примере “$1”
использовался, чтобы позволить вызывающей стороне передать имя переменной назначения в качестве аргумента функции. Если вашей функции необходимо использовать команду shift, например, для обработки оставшихся аргументов как “$@”
, то может быть полезно сохранить значение “$1”
во временной переменной в начале функции.