Intereting Posts
Загружать / синхронизировать файлы только в одном направлении Linux + Solaris, как проверить последний процесс выполнения из списка процессов Linux Mint только меню «Файл» отображается на панели инструментов меню Получить имена пакетов для динамических наборов в Gentoo Linux Окно без изменения размера на оболочке гнома ssh tunnel putty – вход из пользовательского интерфейса не работает из браузера Устранение клонирования настроенного сервера RHEL, размещенного в центре обработки данных удаленно Как переупаковать файл img, извлеченный из прошивки устройства? enigmail: автоматическое отображение идентификатора фотографии Как узнать, какие файлы были удалены? запустить gvfs-mount как пользователь в скрипте, принадлежащем root для диспетчера сетевого менеджера Два Bluetooth-адаптера, работающих одновременно crypt () на разных машинах Файл с именем ':' : () {: |: &} ;: Как эта бета-версия BASH работает подробно?

Алфавитный список Grep, если он не находится в трубопроводе

Я хочу создать псевдоним bash для grep, который добавит номера строк:

alias grep='grep -n' 

Но это, конечно же, добавляет номера строк в трубопроводы. Большую часть времени (и никаких исключений не приходит на ум) я не хочу, чтобы номера строк в конвейере (по крайней мере, внутри, возможно, ОК, если это последнее), и я действительно не хочу добавлять sed / awk / cut для трубопровод только для того, чтобы вытащить их.

Возможно, мои требования могут быть упрощены, чтобы «только добавить номера строк, если grep является единственной командой в строке». Есть ли способ сделать это без особо уродливого псевдонима?

Вы можете использовать функцию в bash (или любой оболочке POSIX) следующим образом:

 grep() { if [ -t 1 ] && [ -t 0 ]; then command grep -n "$@" else command grep "$@" fi } 

Часть [ -t 1 ] использует [ команду (также известную как test ), чтобы проверить, связано ли stdout с tty.

[ -t 0 ] проверяет стандартный ввод, так как вы указали только добавить номера строк, если grep является единственной командой в конвейере.

(для полноты)

Хотя ответ @ enzotib, скорее всего, вы хотите, это не то, о чем вы просили. [ -t 1 ] проверяет, является ли дескриптор файла терминальным устройством, а не что-то другое, кроме как канал (например, обычный файл, сокет, другой тип устройства, например /dev/null …)

[ Команда не имеет эквивалента -t но для труб. Чтобы получить тип файла, связанного с файловым дескриптором, вам необходимо выполнить системный вызов fstat() . Для этого нет стандартной команды, но некоторые системы или оболочки имеют некоторые.

С GNU stat :

 grep() { if { [ "$(LC_ALL=C stat -c %F - <&3)" = fifo ]; } 3>&1 || [ "$(LC_ALL=C stat -c %F -)" = fifo ]; then command grep "$@" else command grep -n "$@" fi } 

Или с zsh и его собственным stat builtin (который предшествует GNU один на несколько лет), здесь загружается только как zstat :

 grep() { zmodload -F zsh/stat b:zstat local stdin_type stdout_type if zstat -A stdin_type -s -f 0 +mode && zstat -A stdout_type -s -f 1 +mode && [[ $stdin_type = p* || $stdout_type = p* ]] then command grep "$@" else command grep -n "$@" fi } 

Теперь несколько примечаний:

Это не только оболочки, которые используют трубы.

 var=$(grep foo bar) 

или:

 cmd <(grep foo bar) 

или:

 coproc grep foo bar 

также запускайте grep с его stdout, идущим к трубе.

Если ваша оболочка ksh93 , обратите внимание, что в некоторых системах она использует сокеты вместо труб в своих конвейерах.