Вот выдержка из моего ответа на сценарий оболочки: проверить имя каталога и преобразовать его в нижний регистр, в котором я демонстрирую не только то, как решить эту проблему с помощью очень простых утилит, указанных в POSIX, я также обращаюсь к , как очень просто сохранить результаты функции в возвращаемом переменная ...
... Как видите, с некоторой помощью я нашел довольно простое и очень мощное решение:
Я могу передать функции своего рода переменную мессенджера и разыменовать любое явное использование $1
имени результирующего аргумента функции с eval
по мере необходимости, а по завершении подпрограммы функции я использую eval
и трюк с цитированием с обратной косой чертой присвоить моей переменной-мессенджеру желаемое значение, даже не зная его имени.
С полным раскрытием, ... (я нашел в этом разделе переменную мессенджера) и на трюки Рича и я также привел выдержку из соответствующей части его страницы под выдержкой из моего собственного ответа.
... ВЫДЕРЖКА: ...
Хотя это еще не строго POSIX, realpath является основным приложением GNU с 2012 года. Полное раскрытие: никогда не слышал об этом, прежде чем заметил это в info coreutils
TOC и сразу подумал о [связанном] вопросе, но использование следующей функции, как показано, должно надежно (скоро POSIXLY?) И, я надеюсь, эффективно предоставить ее вызывающему с абсолютно исходным $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
с абсолютным источником $0
через переменную мессенджера (с заметным исключением, что он сохранит symlinks
) так эффективно, насколько я мог себе представить. выполняется независимо от того, является ли путь уже абсолютным. ...
(незначительное изменение: прежде чем найти realpath
в документации, я, по крайней мере, сократил свою версию (версию ниже), чтобы она не зависела от поля времени (как в первом ps
command), но, честно говоря, после тестирования некоторых я менее убежден, что ps
полностью надежен с точки зрения возможности расширения пути к команде)
С другой стороны, вы можете сделать это:
ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"
eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"
... И из трюков Рича: ...
Возврат строк из функции оболочки
Как видно из вышеупомянутой ловушки подстановки команд, стандартный вывод не является хорошим способом для функций оболочки возвращать строки вызывающей стороне, если только вывод не находится в формате, в котором завершающие символы новой строки не имеют значения. Конечно, такая практика неприемлема для функций, предназначенных для работы с произвольными строками. Так что можно сделать?
Попробуй это:
func () {
body here
eval "$1=\${foo}"
}
Конечно, ${foo}
можно заменить любой заменой. Ключевой уловкой здесь является строка eval и использование экранирования. “$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”
во временной переменной в начале функции.
person
Community
schedule
26.11.2013
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd && echo x)"
- и удалить его без подстановки команды -DIR="${DIR%x}"
. - person l0b0   schedule 24.09.2012mkdir $'\n'
. - person l0b0   schedule 28.03.2013dirname
, и что каталог может начинаться с-
(например,--help
).DIR=$(reldir=$(dirname -- "$0"; echo x); reldir=${reldir%?x}; cd -- "$reldir" && pwd && echo x); DIR=${DIR%?x}
. Может, это перебор? - person Score_Under   schedule 28.04.2015realpath "$0"
? - person Nonny Moose   schedule 10.06.2017dirname
: просто используйтеreldir=${0%/*}
напрямую - person mtraceur   schedule 19.10.2018