Цветной вывод grep: не GREP_OPTIONS, не псевдоним

10

Я хочу цветной вывод grep.

.... Но

  • Стратегия 1: GREP_OPTIONS. Но это не рекомендуется. См. Http://www.gnu.org/software/grep/manual/html_node/Environment-Variables.html.
  • Stragegy 2: GREP_COLORS на первый взгляд выглядит как решение, но это делает что-то другое.
  • Стратегия 3: псевдоним. Это не работает find ... | xargs grep, поскольку xargs не оценивает псевдонимы.
  • Стратегия 4: Напишите простой скрипт-обертку. Нет, я думаю, что это слишком грязно и создает больше проблем, чем решает.
  • Стратегия 5: патч исходного кода
  • Стратегия 6: Свяжитесь с разработчиками grep, попросите замену GREP_OPTIONS
  • Стратегия NICE-и-EASY: ... этого не хватает. Я понятия не имею.

Как это решить?

Спасибо за попытку помочь!

... но я не могу дать награду

Назовите меня грубым, ароматным, оскорбительным, оскорбительным ....

Я вижу только обходные пути - нет решения. Нет ответа удовлетворил вопрос.

Спасибо за старания.

guettli
источник
1
Вы отклонили два предложения использовать скрипт-обертку (ваша Стратегия 4) как «не совсем ответ». Можете ли вы описать, что такое «грязный», «неприятный» или «не совсем ответ»? Может быть, это отдельная проблема, которую можно обойти.
JigglyNaga
2
Стратегия 5 - это исправить исходный код и установить его color_optionна2 ...
don_crissti
2
@JigglyNaga вот мое объяснение, почему скрипт-обертка не является решением. Наша команда управляет несколькими серверами. Меньше тысячи на данный момент, но количество увеличивается. Да, мы используем управление конфигурацией, и было бы легко развернуть сценарий для всех из них. Но я хочу, чтобы все было просто и понятно (подумайте о новых членах команды. Я не хочу их путать). --colorВариант уже имеет значение auto. Я просто не знаю, почему вы не можете активировать его по умолчанию.
Геттли
Вы должны использовать стратегию 4 или 5 - я бы предпочел стратегию 4 с минимальным сценарием dash / sh ( exec grep --color=auto "$@"), опционально с другим именем ( grepcили colorgrep). Это имеет незначительные накладные расходы (и не требует дополнительных параллельных процессов во время выполнения). Причина, по которой вы назвали их «недостаточно простыми», заключается в том, что вы не считаете эту функцию достаточно полезной, чтобы тратить (относительно небольшие) разовые усилия на ее реализацию, и ищете, чтобы кто-то другой сделал ее за вас. Из-за этого ваши «не совсем ответные» комментарии к опубликованным ответам являются довольно грубыми.
Номинальное животное
1
@NominalAnimal Да, вы правы, "не совсем ответ" звучит грубо. Я не носитель языка. Какая формулировка (передача того же сообщения) будет лучше?
Геттли

Ответы:

13

Некоторые из причин, по которым OP указала, что варианты являются неподходящими, не имеют под собой реальной основы. Здесь я покажу, какие эффекты использует стратегия 4 OP:


В большинстве дистрибутивов grepустанавливается в /bin(обычный) или /usr/bin(OpenSUSE, может быть, в другие), и по умолчанию PATHсодержит /usr/local/binдо /binили /usr/bin. Это означает, что если вы создаете /usr/local/bin/grepс

#!/bin/sh
exec /bin/grep --color=auto "$@"

где /bin/shPOSIX-совместимая оболочка, предоставляемая вашим дистрибутивом, обычно bash или dash. Если grepесть /usr/bin, то сделайте это

#!/bin/sh
exec /usr/bin/grep --color=auto "$@"

Накладные расходы этого скрипта минимальны. Это execутверждение означает, что интерпретатор сценария заменяется grepдвоичным; это означает, что оболочка не остается в памяти во grepвремя выполнения. Таким образом, единственные накладные расходы - это одно дополнительное выполнение интерпретатора сценария, то есть небольшая задержка во времени настенных часов. Задержка примерно постоянной (изменяется только в зависимости от того , grepи shуже в кэше страницы или нет, и от того, как полоса пропускания много ввода / вывода доступна), и не зависит от того, как долго grepисполняет или сколько данных он обрабатывает.

Итак, как долго эта задержка, то есть накладные расходы, добавленные сценарием оболочки?

Чтобы выяснить это, создайте приведенный выше скрипт и запустите

time /bin/grep --version
time /usr/local/bin/grep --version

На моей машине первый занимает 0,005 с в реальном времени (при большом количестве прогонов), тогда как второй занимает 0,006 с в реальном времени. Таким образом, накладные расходы на использование оболочки на моей машине составляют 0,001 с (или меньше) за вызов.

Это незначительно.

Я также не вижу ничего «грязного» в этом, потому что многие обычные приложения и утилиты используют один и тот же подход. Чтобы увидеть список таких на вашей машине в /binи /usr/bin, просто запустите

file /bin/* /usr/bin/* | sed -ne 's/:.*shell script.*$//p'

На моей машине выше выход включает в себя egrep, fgrep, zgrep, which, 7z, chromium-browser, ldd, и xfig, которые я использую довольно часто. Если вы не считаете весь свой дистрибутив «грязным» для использования сценариев-оболочек, у вас нет оснований считать такие сценарии-оболочки «грязными».


Что касается проблем, такой скрипт-обертка может вызвать:

Если только человеческие пользователи (в отличие от скриптов) используют версию Grep , что по умолчанию цвета поддержки , если выход является на терминал, то сценарий обертка может быть именем colorgrepили cgrepили независимо от того, что ОП считает нужным.

Это позволяет избежать всех возможных проблем совместимости, поскольку поведение grepне изменяется вообще.


Включение grepпараметров с помощью сценария-оболочки, но таким образом, чтобы избежать каких-либо новых проблем:

Мы можем легко переписать скрипт-обертку для поддержки пользовательского, GREP_OPTSдаже если он GREP_OPTIONSне поддерживается (так как он уже устарел). Таким образом, пользователи могут просто добавить export "GREP_OPTIONS=--color=auto"свой профиль или подобный ему. /usr/local/bin/grepзатем

#!/bin/sh
exec /bin/grep $GREP_OPTIONS "$@"

Обратите внимание, что вокруг нет кавычек $GREP_OPTIONS, поэтому пользователи могут указать более одного параметра.

В моей системе выполнение time /usr/local/bin/grep --versionс GREP_OPTIONSпустым или с GREP_OPTIONS=--color=autoтаким же быстрым выполнением, как и в предыдущей версии сценария оболочки; т.е. обычно выполняется на одну миллисекунду дольше, чем обычный grep.

Это последняя версия, которую я лично рекомендую для использования.


Таким образом, стратегия ОП 4:

  • рекомендуется grepразработчикам

  • тривиально реализовать (две строки)

  • имеет незначительные накладные расходы (дополнительная задержка в одну миллисекунду на вызов на этом конкретном ноутбуке; легко проверяется на каждой машине)

  • может быть реализован в виде скрипта-обёртки, который добавляет GREP_OPTSподдержку (вместо устаревшего / неподдерживаемого GREP_OPTIONS)

  • может быть реализован (как colorgrep/ cgrep), который не затрагивает сценарии или существующих пользователей вообще

Поскольку этот метод уже широко используется в дистрибутивах Linux, это обычный метод, а не «грязный».

Если он реализован как отдельная оболочка ( colorgrep/ cgrep), он не может создавать новые проблемы, так как он вообще не влияет на grepповедение. При реализации в виде сценария-обертки, который добавляет GREP_OPTSподдержку, использование GREP_OPTS=--color=autoимеет те же риски (по сравнению с существующими сценариями), что и при добавлении по умолчанию в исходной версии --color=auto. Таким образом, комментарий о том, что это «создает больше проблем, чем решает», совершенно неверен: никаких дополнительных проблем не создается.

Номинальное животное
источник
3

Документация, которую вы предоставляете с первой стратегией, гласит:

Пожалуйста, используйте псевдоним или скрипт. Например, если grep находится в каталоге '/ usr / bin', вы можете добавить $ HOME / bin к своему PATH и создать исполняемый скрипт $ HOME / bin / grep, содержащий следующее:

#! /bin/sh
export PATH=/usr/bin
exec grep --color=auto --devices=skip "$@"

Так что, если псевдоним для вас невозможен, сценарий-обертка - единственный способ.

STDERR
источник
Это Стратегия 4 ... не совсем ответ.
Геттли
3

Причина, по которой GREP_OPTIONSпеременная устарела, состоит в том, что она имеет тенденцию вызывать проблемы, когда grepвызывается где-то в скрипте, и скрипт не работает с альтернативными опциями, которые приходят из переменной. Если вы напишите скрипт-обертку для grepвас, у вас возникнет та же проблема, если вы не дадите ему другое имя .

$ cat ~/bin/cgrep
#!/bin/sh
exec grep --color=always "$@"
$ find  -exec cgrep  {} +

Кроме того, храните ваши любимые параметры в переменной. В оболочках, отличных от zsh, это неудобно, если параметры содержат символы подстановки ( \[*?), но в противном случае вы можете просто использовать переменную без кавычек, чтобы получить команду с аргументами.

cgrep=(grep --color=always)
find  -exec $cgrep  {} +

Обратите внимание, что GNU и BSD grep могут рекурсивно обрабатывать дерево каталогов, что устраняет необходимость findв сочетании с grepбольшей частью времени.

Жиль "ТАК - прекрати быть злым"
источник
1
Это Стратегия 4 ... не совсем ответ.
Геттли
@ guettli, это правильный ответ. Если вам нужна команда с другим поведением, то grepвам нужна команда с другим именем, или, если вы сохраняете то же имя, вы нарушите сценарии, которые ожидают оригинального / стандартного поведения. Это самый чистый и не доставляет дополнительных хлопот .
Стефан
@ StéphaneChazelas да, ты прав. Это правильный ответ с вашей точки зрения.
Геттли
1

Самое простое - использовать псевдоним (стратегия 3). Если вы действительно заботитесь о xargsкоманде, вы все равно можете переопределить ее с помощью функции bash.

alias grep='grep --color'
xargs() {
    local args
    for ((i=1; i<=$#; i++))
    do
            if [[ "-E -L -P -I -s -d" == *"${!i}"* ]]; then
                    ((i=i+1))
            elif [[ ${!i:0:1} != "-" ]]; then
                    if [[ ${!i} == "grep" ]]; then
                            args="--color"
                    fi
                    /usr/bin/xargs ${@:1:i} $args ${@:i+1}
                    return;
            fi
    done
}

Но это не лучше, чем использование команды-оболочки, которая кажется рекомендуемым решением для grepкоманды:

/usr/local/bin/grep:

#!/bin/bash
/bin/grep --color "$@"

По моему скромному мнению, вы должны связаться с grepкомандой разработчиков, чтобы попросить их предоставить простую замену GREP_OPTIONSпеременной, которая включит цвет в grepсоответствии с некоторой переменной среды.

Для них было бы довольно просто включить опцию по умолчанию colorили когда GREP_COLORSона была установлена.

Адам
источник
1
Спасибо за "... вы должны связаться с командой разработчиков grep ...". Это дает мне положительный отзыв. Теперь я знаю, что я не единственный, кто думает, что чего-то здесь не хватает.
Геттли
Я добавил ваш комментарий "... вы должны связаться с командой разработчиков grep ..." в качестве стратегии6 к вопросу. До сих пор это мой любимый ответ.
Геттли
0

Это решение из верхнего ответа от @NominalAnimal, но с обычным grep: ...предупреждением (вместо /bin/grep: ...):

#!/bin/bash
exec -a grep /bin/grep --color=auto "$@"
Кирилл Булыгин
источник
Я умею писать обертки. Оболочка не является решением в этом контексте.
Геттли
@guettli Ну, ответ не предназначен для точного решения вашей ситуации ... Если комментарии имеют те же функции форматирования, что и ответы, это будет комментарий. (И у меня были подобные правки, отклоненные как не предназначенные первоначальным автором или чем-то еще.) Что касается вашей ситуации, я думаю, что правильный буквальный ответ на ваш вопрос: что другой «Стратегии NICE-and-EASY» не существует.
Кирилл Булыгин