Grep alias - nomor baris kecuali ada dalam pipa

25

Saya ingin membuat alias bash untuk grep yang menambahkan nomor baris:

alias grep='grep -n'

Tapi itu, tentu saja, menambahkan nomor baris ke saluran pipa juga. Sebagian besar waktu (dan tidak ada pengecualian muncul dalam pikiran) Saya tidak ingin nomor baris dalam pipa (setidaknya secara internal, mungkin OK jika itu yang terakhir), dan saya tidak benar-benar ingin menambahkan sed / awk / cut ke pipa hanya untuk mengambilnya.

Mungkin persyaratan saya dapat disederhanakan menjadi "hanya menambahkan nomor baris jika grep adalah satu-satunya perintah di telepon." Apakah ada cara untuk melakukan ini tanpa alias jelek?

Kevin
sumber

Jawaban:

27

Anda bisa menggunakan fungsi dalam bash (atau shell POSIX) seperti ini:

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

Bagian ini [ -t 1 ]menggunakan [perintah (juga dikenal sebagai test) untuk memeriksa apakah stdout dikaitkan dengan tty.

The [ -t 0 ]cek input standar, juga, karena Anda ditentukan untuk hanya menambahkan nomor baris jika grepadalah hanya perintah di dalam pipa.

enzotib
sumber
5
Dan lakukan pengujian [[ -t 0 && -t 1 ]]jika Anda hanya ingin nomor baris jika input standar dan output standar terhubung ke terminal.
Gilles 'SANGAT berhenti menjadi jahat'
3

(untuk kelengkapan)

Meskipun jawaban @ enzotib kemungkinan besar adalah yang Anda inginkan, itu bukan apa yang Anda minta. [ -t 1 ]memeriksa apakah deskriptor file adalah perangkat terminal, bukankah itu selain pipa (seperti file biasa, soket, jenis perangkat lain seperti /dev/null...)

The [perintah tidak memiliki setara -ttetapi untuk pipa. Untuk mendapatkan jenis file yang terkait dengan deskriptor file, Anda perlu melakukan fstat()panggilan sistem di atasnya. Tidak ada perintah standar untuk melakukan itu, tetapi beberapa sistem atau shell memiliki beberapa.

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

Atau dengan zshdan statbawaannya sendiri (yang mendahului GNU beberapa tahun kemudian), zstathanya dimuat di sini :

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
}

Sekarang beberapa catatan:

Bukan hanya shell pipelines yang menggunakan pipa.

var=$(grep foo bar)

atau:

cmd <(grep foo bar)

atau:

coproc grep foo bar

juga berjalan grepdengan stdout pergi ke pipa.

Jika shell Anda ksh93, perhatikan bahwa pada beberapa sistem, ia menggunakan socketpairs bukan pipa di pipelines-nya.

Stéphane Chazelas
sumber