У меня есть относительно длинный набор сценариев, которые я сейчас оцениваю и вношу изменения в исходный код, чтобы выполнить один и тот же набор сценариев как в 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...]
0
SuperTonic09 6 Сен 2016 в 22:04

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.

3
jlliagre 7 Сен 2016 в 09:23

Как насчет того, чтобы поместить что-то подобное в начало ваших скриптов:

[ -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, чтобы он имел наивысший приоритет.

3
redneb 6 Сен 2016 в 19:07

Одно из решений - поставить после 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
0
Gilles Quenot 6 Сен 2016 в 19:09