Bagaimana cara grep untuk tab tanpa menggunakan tab literal dan mengapa tidak bekerja?

146

Ketika saya mencari tab dalam file dengan (e) grep saya menggunakan tab litteral ( ^v + <tab>). Saya tidak dapat menggunakan \tsebagai pengganti tab dalam ekspresi reguler. Dengan mis. Ungkapan ini bekerja dengan sangat baik.

Jadi apakah ada kemungkinan untuk menggunakan pengganti non-litteral untuk <tab>dan apa latar belakang untuk tidak bekerja / tidak ditafsirkan \t?

Lasall
sumber
stackoverflow.com/questions/1825552/grep-a-tab-in-unix
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

206

grep menggunakan ekspresi reguler seperti yang didefinisikan oleh POSIX . Untuk alasan apa pun POSIX belum didefinisikan \tsebagai tab.

Anda memiliki beberapa alternatif:

  • beri tahu grep untuk menggunakan ekspresi reguler seperti yang didefinisikan oleh perl (perl memiliki \tsebagai tab):

    grep -P "\t" foo.txt

    halaman manual memperingatkan bahwa ini adalah fitur "eksperimental". setidaknya \ttampaknya berfungsi dengan baik. tetapi fitur perl regex yang lebih canggih mungkin tidak.

  • gunakan printf untuk mencetak karakter tab untuk Anda:

    grep "$(printf '\t')" foo.txt
  • gunakan karakter tab literal:

    grep "^V<tab>" foo.txt

    yaitu: ketik grep ", lalu tekan ctrl+v, lalu tekan tab, lalu ketik " foo.txt. menekan ctrl+vdi terminal menyebabkan kunci berikutnya diambil kata demi kata. itu berarti terminal akan memasukkan karakter tab bukannya memicu beberapa fungsi yang terikat pada tombol tab.

  • gunakan fitur kutip ansi c dari bash:

    grep $'\t' foo.txt

    ini tidak bekerja di semua shell.

  • gunakan awk:

    awk '/\t/'
  • gunakan sed:

    sed -n '/\t/p'

Lihat artikel wikipedia tentang ekspresi reguler untuk tinjauan umum dari kelas karakter yang ditentukan dalam POSIX dan sistem lainnya.

lesmana
sumber
mendasarkan pada jawaban enzotib izinkan saya menambahkan yang berikut: grep $'\t' foo.txt(tapi saya biasanya akan menulis fgrepsebagai gantinya grep)
Walter Tross
Saya membutuhkan ini, dikombinasikan dengan menggunakan nilai variabel lingkungan. Saya menggunakan grep "$(printf '\t')${myvar}" foo.txt. Itu bekerja dengan baik. Dengan beberapa percobaan, saya tidak bisa mendapatkan formulir terakhir yang berfungsi.
sancho.s
1
Apakah ada alasan yang greptidak bisa ditafsirkan secara diam-diam \tsebagai tab? Apakah POSIX mengharuskan itu \tberarti sesuatu yang lain? Mungkin itu seharusnya cocok dengan hanya literal \ diikuti oleh t?
Aaron McDaid
Mungkin perlu dicatat bahwa BSD (termasuk OSX) grep, tidak memiliki opsi -P.
TextGeek
Dari halaman manual This is highly experimental and grep -P may warn of unimplemented features.Mungkin bukan ide yang baik untuk digunakan -Pdalam sistem lawas. The printfpilihan yang lebih baik
Avindra Goolcharan
13

Ini bukan jawaban yang ingin Anda dengar, tetapi kemungkinan penggunaan escape sequence disediakan oleh bash

command | grep $'\t'

(jangan memasukkannya ke dalam tanda kutip ganda!).

enzotib
sumber
1
tidak perlu untuk -E (yang dicari adalah tidak ada regex). Juga tidak perlu pipa dari perintah. Yang mengatakan, terima kasih telah menunjukkan fitur bash yang cukup diabaikan ini (string single-quote didahului dengan $)
Walter Tross
2
Memang, saya menyarankan agar @enzotib mengedit jawabannya secara sederhana grep $'\t'.
Teemu Leisti
Harus ditekankan bahwa ini adalah fitur bash dan akan (diam-diam!) Melakukan hal yang salah jika dieksekusi oleh beberapa shell lain (seperti dash, yang merupakan default untuk skrip shell di Ubuntu dan lainnya)
xjcl
2

awk '/\t/' adalah solusi favorit saya:

printf 'a\t\nb' | awk '/\t/'

Output: a\t.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber
1

Satu selalu dapat menggunakan ascii hex-code untuk tab:

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

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

$ grep $'\x9' input.txt                                            
one two
Sergiy Kolodyazhnyy
sumber