
Пытаясь расшифровать некоторые скрипты, написанные бывшими сотрудниками моей нынешней компании, во многих из них я наткнулся на следующие операторы, которые назначают переменные некоторым командам, как показано ниже:
CAT=cat
GREP=grep
SED=sed
Далее в скрипте я вижу, что они использовали эти переменные вместо обычных команд:
$GREP -v "^#" `dirname $0`/abcdfilename | while read line
do
<some loop operations>
done
Я не вижу смысла в использовании этой переменной вместо использования grep
напрямую. У меня есть вопросы:
- Есть ли смысл использовать grep или sed (в нашем случае) таким образом?
- Является ли это результатом того, что кто-то пытается написать сценарий с намерением сделать его более сложным для понимания другим человеком?
- Или это просто пример плохого сценария?
решение1
Существуют различные реализации стандартной команды в системе. Как в Solaris 10 и более ранних версиях, у вас есть /bin/sh
старая оболочка Bourne и /usr/xpg4/bin/sh
совместимая с POSIX оболочка. Или в OSX у вас есть BSD sed при вызове sed
и GNU sed при вызове gsed
. Вы можете выбрать, какую реализацию вы хотите использовать в своем скрипте.
Так что проще изменить реализацию в вашем скрипте, когда вы использовали переменную. Когда вам нужен GNU sed:
SED=gsed
Если вы не используете переменную, то вам необходимо заменить все вхождения sed
в вашем скрипте. Хотя вы можете сделать это легко, это считается плохой практикой программирования.
решение2
Существует аргумент в пользу превращения практически любого элемента, который вы многократно используете в сценарии, в переменную, поскольку тогда вы можете переопределить его один раз и распространить на весь сценарий.
Вы можете утверждать, что по сути то же самое можно сделать с помощью простого поиска/замены sed, но многие пользователи опасаются поиска/замены, поскольку не так уж сложно случайно заменить то, что вы не собирались заменять.
На самом деле, я бы предложил следующее улучшение по сравнению с существующей версией:
GREP=${GREP:-/bin/grep}
это означает, что GREP будет установлен на то, что пользователь установил в оболочке, или, если НЕ установлено, то на /bin/grep
Таким образом, пользователь может переопределить «grep» на лету.
$ export GREP=/bin/fgrep
$ ./path/to/script.sh
решение3
Вероятно, это пример преждевременной оптимизации.
Сколько альтернатив есть у этой машины, илилюбоймашина есть длясед,грэп, иawk? Я бы поспорил, что универсальное среднее значение близко к 1,0. Учитывая два варианта на конкретной машине, каковы шансы того, что реализации будут отличаться таким образом, что скрипт не будет работать с версией, найденной в PATH, и будет работать с другой? Если это произойдет, то более вероятно, что решением будет изменение скрипта или PATH? Если изменение скрипта окажется ответом, каковы шансы найти хотя бы один вызовгрэпвместо$GREP? Колода подтасована против необходимости какой-либо косвенности и против того, чтобы она работала так, как задумано, если она когда-либо понадобится.
Я бы не стал бороться с культурой. Если в вашем магазине есть какие-то предпочтения$GREPили/usr/bin/grepили простогрэп, я бы, наверное, пошел, чтобы ужиться. В противном случае, KISS: избегайте косвенности, пока в ней не возникнет необходимость.