У меня есть относительно длинный набор сценариев, которые я сейчас оцениваю и вношу изменения в исходный код, чтобы выполнить один и тот же набор сценариев как в Linux, так и в SunOS. Часть кода имеет простой grep, например:
#Linux
echo -e "\n foo \n bar \n test ok" | grep -Evw 'foo|bar'
Моя попытка переноса работает нормально, если перевести как:
#SunOS
echo -e "\n foo \n bar \n test ok" | /usr/xpg4/bin/grep -Ev 'foo|bar'
Есть ли способ написать один оператор в Bash для работы в обоих сценариях? Или я должен быть мысленно подготовлен к реализации дополнительных операторов if / else для каждой операционной системы?
В этом случае кажется, что / bin / grep может выполнять как регулярное выражение, так и сопоставление слов, но тогда с / usr / bin / grep мы можем выполнять только слово, а не оба:
$ echo -e "\n foo \n bar \n test ok" | grep -Evw 'foo|bar'
grep: illegal option -- E
Usage: grep [-c|-l|-q] -bhinsvw pattern file . . .
$ echo -e "\n foo \n bar \n test ok" | /usr/xpg4/bin/grep -Evw 'foo|bar'
Usage: grep [-c|-l|-q] [-bhinsvwx] pattern_list [file ...]
grep [-c|-l|-q] [-bhinsvwx] [-e pattern_list]... [-f pattern_file]... [file...]
grep -E [-c|-l|-q] [-bhinsvx] pattern_list [file ...]
grep -E [-c|-l|-q] [-bhinsvx] [-e pattern_list]... [-f pattern_file]... [file...]
grep -F [-c|-l|-q] [-bhinsvx] pattern_list [file ...]
grep -F [-c|-l|-q] [-bhinsvx] [-e pattern_list]... [-f pattern_file]... [file...]
3 ответа
Есть ли способ написать один оператор в Bash для работы в обоих сценариях?
Да.
Или я должен быть мысленно готов начать реализацию дополнительных операторов if / else для каждой операционной системы?
Нет, по возможности этого следует избегать. В вашем случае все можно сделать с помощью стандартных команд, поэтому нет необходимости добавлять код, специфичный для ОС.
Вот портативный способ сделать это. Это должно работать на всех Unix-подобных машинах:
PATH=`getconf PATH`:$PATH # Should be done once at the beginning of scripts.
printf "\n foo \n bar \n test ok" | grep -Ev '\<foo\>|\<bar>\'
getconf PATH
возвращает PATH к POSIX-совместимым командам во всех Unix / Unix-подобных реализациях.
printf
следует использовать, когда требуются команды форматирования, echo
не может надежно использоваться, поскольку его поведение не определено даже в POSIX.
\<...\>
- это способ POSIX определять границы слов с помощью расширенных регулярных выражений.
Обратите внимание, что я использовал не $(getconf PATH)
, а более старый синтаксис `getconf`
, потому что в Solaris 10 вы можете использовать устаревшую оболочку Bourne.
Как насчет того, чтобы поместить что-то подобное в начало ваших скриптов:
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin:$PATH"
Тогда в обеих системах будет работать следующая строка:
echo -e "\n foo \n bar \n test ok" | grep -Evw 'foo|bar'
Идея, конечно же, состоит в том, чтобы проверить, существует ли каталог /usr/xpg4/bin
, и если он есть, мы можем предположить, что он включает grep
, который поддерживает нужные нам параметры (предположительно GNU grep
) . Так что просто добавьте этот каталог в начало $PATH
, чтобы он имел наивысший приоритет.
Одно из решений - поставить после shebang :
grep_path=/usr/lib/gnu/bin # <- EDIT ME
PATH=$grep_path:$PATH
# will work on any platform with a GNU grep
grep foobar file
Похожие вопросы
Новые вопросы
linux
ВНИМАНИЕ: Все вопросы по Linux должны быть связаны с программированием; те, которые не будут закрыты. Используйте этот тег, только если ваш вопрос касается программирования с использованием API-интерфейсов Linux или поведения, специфичного для Linux, а не только потому, что вы запускаете свой код в Linux. Если вам нужна поддержка Linux, вы можете попробовать https://unix.stackexchange.com или сайт Stack Exchange конкретного дистрибутива Linux, например https://askubuntu.com или https://elementaryos.stackexchange.com/.