Làm cách nào để grep cho các tab mà không sử dụng các tab theo nghĩa đen và tại sao không hoạt động?


146

Khi tôi tìm kiếm các tab trong một tệp có (e) grep, tôi sử dụng tab xả rác ( ^v + <tab>). Tôi không thể sử dụng \tnhư là một thay thế cho các tab trong biểu thức thông thường. Với ví dụ sed biểu hiện này hoạt động rất tốt.

Vì vậy, có bất kỳ khả năng để sử dụng một thay thế không xả rác cho <tab>và những nền tảng cho một không làm việc / không được giải thích là \tgì?


Câu trả lời:


206

grep đang sử dụng các biểu thức chính quy theo định nghĩa của POSIX . Vì lý do nào POSIX chưa được xác định \tlà tab.

Bạn có một vài lựa chọn thay thế:

  • báo cho grep sử dụng các biểu thức chính quy như được định nghĩa bởi perl (perl có \tdưới dạng tab):

    grep -P "\t" foo.txt

    trang người đàn ông cảnh báo rằng đây là một tính năng "thử nghiệm". ít nhất là \tcó vẻ hoạt động tốt. nhưng các tính năng regex perl tiên tiến hơn có thể không.

  • sử dụng printf để in một ký tự tab cho bạn:

    grep "$(printf '\t')" foo.txt
  • sử dụng ký tự tab theo nghĩa đen:

    grep "^V<tab>" foo.txt

    đó là: gõ grep ", sau đó nhấn ctrl+v, sau đó nhấn tab, sau đó gõ " foo.txt. nhấn ctrl+vtrong thiết bị đầu cuối làm cho khóa tiếp theo được lấy nguyên văn. điều đó có nghĩa là thiết bị đầu cuối sẽ chèn một ký tự tab thay vì kích hoạt một số chức năng bị ràng buộc với phím tab.

  • sử dụng tính năng trích dẫn ansi c của bash:

    grep $'\t' foo.txt

    Điều này không hoạt động trong tất cả các vỏ.

  • sử dụng awk:

    awk '/\t/'
  • sử dụng sed:

    sed -n '/\t/p'

Xem bài viết trên wikipedia về các biểu thức chính quy để biết tổng quan về các lớp ký tự được xác định trong POSIX và các hệ thống khác.


dựa trên câu trả lời của enzotib, hãy để tôi thêm vào như sau: grep $'\t' foo.txt(nhưng tôi thường viết fgrepthay vì grep)
Walter Tross

Tôi cần điều này, kết hợp với việc sử dụng giá trị của biến môi trường. Tôi đã sử dụng grep "$(printf '\t')${myvar}" foo.txt. Nó hoạt động tốt. Với một vài lần thử, tôi không thể có được hình thức cuối cùng để làm việc.
sancho.s

1
Có bất kỳ lý do mà đơn giản grepkhông thể âm thầm giải thích \tnhư tab? POSIX có yêu cầu điều đó \tcó nghĩa gì khác không? Có lẽ nó chỉ phù hợp với một nghĩa đen \ theo sau t?
Aaron McDaid

Có lẽ đáng chú ý là BSD (bao gồm cả OSX) grep, thiếu tùy chọn -P.
TextGeek

Từ trang người đàn ông This is highly experimental and grep -P may warn of unimplemented features.Có lẽ không phải là một ý tưởng tốt để sử dụng -Ptrong các hệ thống cũ. Sự printflựa chọn là tốt hơn
Avindra Goolcharan

13

Đây không phải là câu trả lời chính xác mà bạn muốn nghe, nhưng có thể sử dụng các chuỗi thoát được cung cấp bởi bash

command | grep $'\t'

(đừng đặt nó vào dấu ngoặc kép!).


1
không cần cho -E (những gì được tìm kiếm là không có regex). Cũng không cần phải ống từ một lệnh. Điều đó nói rằng, cảm ơn bạn đã chỉ ra tính năng khá bị bỏ qua này của bash (chuỗi trích dẫn đơn trước $)
Walter Tross

2
Thật vậy, tôi đề nghị @enzotib chỉnh sửa câu trả lời một cách đơn giản grep $'\t'.
Teemu Leisti

Cần nhấn mạnh rằng đây là một tính năng của bash và sẽ (âm thầm!) Làm sai nếu được thực thi bởi một số shell khác (chẳng hạn như dấu gạch ngang, là mặc định cho các tập lệnh shell trên Ubuntu và các tập lệnh khác)
xjcl


1

Người ta luôn có thể sử dụng mã hex ascii cho tab:

$ echo "one"$'\t'"two" > input.txt                                 

$ grep -P "\x9" input.txt                                          
one two

$ grep $'\x9' input.txt                                            
one two
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.