Grep alias: numeri di riga a meno che non siano presenti in una pipeline


25

Voglio creare un alias bash per grep che aggiunge numeri di riga:

alias grep='grep -n'

Ma questo, naturalmente, aggiunge anche i numeri di linea alle condutture. Il più delle volte (e non mi vengono in mente eccezioni) Non voglio numeri di riga all'interno di una pipeline (almeno internamente, probabilmente OK se è l'ultimo), e non voglio davvero aggiungere un sed / awk / cut a la pipeline solo per eliminarli.

Forse i miei requisiti potrebbero essere semplificati per "aggiungere numeri di riga solo se grep è l'unico comando sulla riga". C'è un modo per farlo senza un alias particolarmente brutto?

Risposte:


27

È possibile utilizzare una funzione in bash (o qualsiasi shell POSIX) in questo modo:

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

La [ -t 1 ]parte utilizza il [comando (noto anche come test) per verificare se stdout è associato a un tty.

Lo [ -t 0 ]standard input controlli, così, dal momento che si è specificato di solo aggiungere numeri di riga se grepè l' unico comando nella pipeline.


5
E fai il test [[ -t 0 && -t 1 ]]se vuoi solo i numeri di linea se sia l'ingresso standard che l'uscita standard sono collegati a un terminale.
Gilles 'SO-smetti di essere malvagio' il

3

(per completezza)

Mentre la risposta di @ enzotib è molto probabilmente quello che vuoi, non è quello che hai chiesto. [ -t 1 ]controlla se il descrittore di file è un dispositivo terminale, non che sia qualcosa di diverso da una pipe (come un file normale, un socket, un altro tipo di dispositivo come /dev/null...)

Il [comando non ha equivalenti di -tma per pipe. Per ottenere il tipo di file associato a un descrittore di file, è necessario eseguire la fstat()chiamata di sistema su di esso. Non esiste un comando standard per farlo, ma alcuni sistemi o shell ne hanno.

Con 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
}

O con zshe il suo statbuiltin (che precede quello di GNU di qualche anno), qui caricato come zstatunico:

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
}

Ora alcune note:

Non sono solo le pipeline a guscio che utilizzano i tubi.

var=$(grep foo bar)

o:

cmd <(grep foo bar)

o:

coproc grep foo bar

funziona anche grepcon il suo stdout che va in una pipe.

Se la tua shell lo è ksh93, nota che su alcuni sistemi, utilizza socket al posto dei tubi nelle sue tubazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.