Grep alias - números de linha, a menos que esteja em um pipeline

23

Eu quero criar um alias de bash para o grep que adicione números de linha:

alias grep='grep -n'

Mas isso, claro, também adiciona números de linhas a pipelines. Na maior parte do tempo (e nenhuma exceção me vem à mente) Eu não quero números de linha dentro de um pipeline (pelo menos internamente, provavelmente OK se for o último), e eu realmente não quero adicionar um sed / awk / cut ao o gasoduto só para tirá-los.

Talvez meus requisitos possam ser simplificados para "adicionar apenas números de linha, se o grep for o único comando na linha". Existe alguma maneira de fazer isso sem um apelido particularmente feio?

    
por Kevin 28.11.2011 / 17:36

2 respostas

25

Você poderia usar uma função no bash (ou qualquer shell POSIX) assim:

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

A parte [ -t 1 ] usa o comando [ (também conhecido como test ) para verificar se a stdout está associada a um tty.

O [ -t 0 ] verifica a entrada padrão, já que você especificou adicionar apenas números de linha se grep for o comando somente no pipeline.

    
por 28.11.2011 / 17:55
2

(por completude)

Embora a resposta da enzotib seja provavelmente o que você quer, não é o que você pediu. [ -t 1 ] verifica se o descritor de arquivo é um dispositivo de terminal, não que seja algo diferente de um canal (como um arquivo normal, um soquete, outro tipo de dispositivo como /dev/null ...)

O comando [ não tem equivalente de -t , mas para pipes. Para obter o tipo de arquivo associado a um descritor de arquivo, você precisa executar a chamada do sistema fstat() . Não existe um comando padrão para fazer isso, mas alguns sistemas ou shells têm alguns.

Com o 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
}

Ou com zsh e seu próprio stat builtin (que é anterior a um do GNU em alguns anos), aqui carregado como zstat apenas:

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
}

Agora, algumas notas:

Não são apenas pipelines shell que usam pipes.

var=$(grep foo bar)

ou:

cmd <(grep foo bar)

ou:

coproc grep foo bar

também executa grep com seu stdout indo para um pipe.

Se o seu shell for ksh93 , observe que em alguns sistemas, ele usa pares de soquetes em vez de tubos em seus pipelines.

    
por 21.10.2016 / 08:49