2016-07-27 2 views
5

Там в BashКак использовать POSIXLY_CORRECT в grep?

переменная POSIXLY_CORRECT

POSIXLY_CORRECT

Если эта переменная в среде при запуске Bash, оболочка переходит в режим POSIX (см Баш режим POSIX) перед чтением стартап файлов, как если бы была опция -posix invocation. Если это набора в то время как оболочка работает, Bash включает режим POSIX, как если бы команды

set -o posix 

была казнена.

мне сказали, что некоторые варианты grep не POSIX и поэтому я подтвердил в The Open Group Base Specifications Issue 6 for grep. Так что я проверил GNU grep manual и нашел:

Grep поставляется с богатым набором опций: некоторые из POSIX и некоторые из них являются расширениями GNU. Длинные имена опций всегда являются расширением GNU, даже для опций, относящихся к спецификациям POSIX. Параметры, которые являются , указанные POSIX под их короткими именами, явно помечены как , что облегчает POSIX-переносное программирование. Несколько имен опций - , предназначенные для совместимости со старыми или более экзотическими реализациями.

И это также упоминает:

2.2 Environment Variables

Поведение Grep зависит от следующих переменных среды.

POSIXLY_CORRECT
Если установлено, Grep ведет себя как требует POSIX; В противном случае grep ведет себя как другие программы GNU. POSIX требует, чтобы параметры, следующие за именами файлов, считались именами файлов; по умолчанию такие параметры переставляются в начало списка операндов и рассматриваются как параметры. Кроме того, POSIXLY_CORRECT отключает специальную обработку недопустимого выражения скобки. См. Недопустимый-скотч-expr.

Используя часть длинные имена опций всегда расширение GNU, даже для вариантов, которые от спецификаций POSIX я сказал: давайте попробуем переменную POSIXLY_CORRECT против этого.

Так что я действительно пытался что-то, что не является POSIX:

$ echo "HELLO" | grep --ignore-case 'hello' 
HELLO 

Но к моему удивлению, он также работает установив его:

$ echo "HELLO" | POSIXLY_CORRECT=1 grep --ignore-case 'hello' 
HELLO 

Что я делаю неправильно? Должен ли набор POSIXLY_CORRECT сделать grep не распознать длинное имя параметра?

То же самое происходит при использовании опции (например -C), не POSIX:

$ POSIXLY_CORRECT=1 grep -C 2 '2' <<< "1 
2 
3" 
1 
2 
3 

Как делать все-таки работает set -o posix раньше.

+0

'grep' - внешняя программа, это не часть оболочки. – Barmar

+0

Попробуйте 'export POSIXLY_CORRECT' – cdarke

+1

@cdarke Когда вы поместите назначение переменной в начале команды, оно автоматически экспортирует его. – Barmar

ответ

6

С GNU grep руководство:

POSIXLY_CORRECT

Если установлено, grep ведет себя, как требует POSIX; в противном случае grep ведет себя как другие программы GNU. POSIX требует, чтобы параметры , следующие за именами файлов, должны рассматриваться как имена файлов; по умолчанию такие параметры переставляются в начало списка операндов и рассматриваются как параметры. Кроме того, POSIX требует, чтобы нераспознанные параметры были диагностированы как «незаконные», , но поскольку они не противоречат закону, по умолчанию диагностирует их как «недействительные». POSIXLY_CORRECT также отключает _N_GNU_nonoption_argv_flags_, описанный ниже.

Это означает, что единственное, что установка POSIXLY_CORRECT в среде делает для GNU grep является то, что он не имеет права переставлять опции, которые происходят после того, как имя файла, так что расположены на передней панели. Это не делает его не принимать флаги командной строки, отличные от POSIX.

Так давайте попробуем что:

$ ggrep "hello" myfile -v 

$ env POSIXLY_CORRECT=1 ggrep "hello" myfile -v 
ggrep: -v: No such file or directory 

(GNU grep называется ggrep на моей системе BSD)

часть о «непризнанных опций» в руководстве, что GNU grep делает по умолчанию, т.е.флаг -g будет диагностирован как "недействительный" под обоими POSIXLY_CORRECT и без него. Так, например, --ignore-case - это действительный вариант (хотя и не POSIX), это не диагностируется как «недействительный» с POSIXLY_CORRECT.

В общем, проверьте документацию на внешние утилиты, как они ведут себя под POSIXLY_CORRECT (если они вообще ухаживают). Руководство пользователя bash может только сообщить вам, как эта оболочка и ее встроенные команды подвержены влиянию.

+2

Вы избили меня с небольшим размахом. Может быть, подчеркнуть, что документация для Bash применима только к Bash и что параметр 'POSIXLY_CORRECT' делает для' grep' именно то, что говорится в руководстве 'grep'. – tripleee

1

Во-первых, переменная POSIXLY_CORRECT, используемая несколькими инструментами GNU и библиотечными функциями, является попыткой быть более корректной, она не гарантирует, что инструменты GNU ведут себя строго в соответствии с POSIX.


GNU grep сам не читает переменную POSIXLY_CORRECT на всех, когда дело доходит до опции синтаксического анализа. GNU grep использует функцию glibc getopt_long, чтобы проанализировать ее варианты. Эта функция соответствует переменной окружения POSIXLY_CORRECT, но только ограниченным образом. Проверьте man getopt_long:

POSIXLY_CORRECT

Если этот параметр установлен, то обработка вариант останавливается, как только nonoption аргумент встречается.

... и исходный код GNU grep

Такое поведение является одинаковым для всех программ, которые связываются с Glibc и использованием getopt_long. Это не относится к grep.

+0

Итак, это было мое непонимание этой переменной. Я думал, POSIXLY_CORRECT заставит меня вернуться в историю к версии POSIX 'grep', а это не так. – fedorqui

+0

Нет, это не так. Я думаю, что это всегда компромисс, сложность кода, производительность, обратная совместимость и да, соответствие posix :) – hek2mgl

Смежные вопросы