Bí danh Grep - số dòng trừ khi nó nằm trong đường ống


25

Tôi muốn tạo một bí danh bash cho grep có thêm số dòng:

alias grep='grep -n'

Nhưng điều đó, tất nhiên, cũng thêm số dòng vào đường ống. Hầu hết thời gian (và không có trường hợp ngoại lệ nào xuất hiện) Tôi không muốn số dòng trong một đường ống (ít nhất là trong nội bộ, có thể là ổn nếu nó kéo dài) và tôi thực sự không muốn thêm sed / awk / cut vào các đường ống chỉ để đưa họ ra.

Có lẽ các yêu cầu của tôi có thể được đơn giản hóa thành "chỉ thêm số dòng nếu grep là lệnh duy nhất trên dòng." Có cách nào để làm điều này mà không có bí danh đặc biệt xấu xí?

Câu trả lời:


27

Bạn có thể sử dụng một hàm trong bash (hoặc bất kỳ shell POSIX nào) như thế này:

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

Phần này [ -t 1 ]sử dụng [lệnh (còn được gọi là test) để kiểm tra xem thiết bị xuất chuẩn có được liên kết với một tty không.

Cũng [ -t 0 ]kiểm tra đầu vào tiêu chuẩn, vì bạn đã chỉ định chỉ thêm số dòng nếu greplà lệnh duy nhất trong đường ống.


5
Và thực hiện kiểm tra [[ -t 0 && -t 1 ]]nếu bạn chỉ muốn số dòng nếu cả đầu vào tiêu chuẩn và đầu ra tiêu chuẩn được kết nối với một thiết bị đầu cuối.
Gilles 'SO- ngừng trở nên xấu xa'

3

(cho đầy đủ)

Mặc dù câu trả lời của @ enzotib có lẽ là những gì bạn muốn, nhưng đó không phải là những gì bạn yêu cầu. [ -t 1 ]kiểm tra xem bộ mô tả tệp có phải là thiết bị đầu cuối không, đó không phải là bất kỳ thứ gì khác ngoài ống (như tệp thông thường, ổ cắm, một loại thiết bị khác như /dev/null...)

Các [lệnh không có tương đương -tnhưng đối với đường ống. Để có được loại tệp được liên kết với một bộ mô tả tệp, bạn cần thực hiện fstat()cuộc gọi hệ thống trên nó. Không có lệnh tiêu chuẩn để làm điều đó, nhưng một số hệ thống hoặc hệ vỏ có một số.

Với 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
}

Hoặc với zshstatnội dung dựng sẵn của nó (trước một vài năm của GNU), ở đây chỉ được tải dưới dạng 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
}

Bây giờ một vài lưu ý:

Đó không chỉ là đường ống vỏ sử dụng đường ống.

var=$(grep foo bar)

hoặc là:

cmd <(grep foo bar)

hoặc là:

coproc grep foo bar

cũng chạy grepvới thiết bị xuất chuẩn của nó đi đến một đường ống.

Nếu vỏ của bạn là ksh93, lưu ý rằng trên một số hệ thống, nó sử dụng ổ cắm thay vì đường ống trong đường ống của nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.