Bagaimana cara saya grep
tab (\ t) dalam file di platform Unix?
Bagaimana cara saya grep
tab (\ t) dalam file di platform Unix?
Jawaban:
Jika menggunakan GNU grep, Anda dapat menggunakan reg-style Perl:
grep -P '\t' *
-P
opsi.
Caranya adalah dengan menggunakan $ sign sebelum tanda kutip tunggal . Ini juga berfungsi untuk memotong dan alat lainnya.
grep $'\t' sample.txt
zsh
juga, sejauh yang saya tahu. Bisakah Anda mengomentari apa semantik dari $
tanda itu?
$'\t'' '
. Sebuah contoh nyata yang menunjukkan itu berfungsi juga dengan sh (bukan hanya bash, yang tidak secara default diinstal pada Android) adalah busybox grep -oE '^nodev'$'\t''fuse$' /proc/filesystems
.
Saya tidak pernah berhasil membuat metacharacter '\' bekerja dengan grep. Namun saya menemukan dua solusi alternatif:
<Ctrl-V> <TAB>
(menekan Ctrl-V lalu mengetik tab)foo | awk '/\t/'
| awk '/\t/'
solusi akan bekerja untuk semua kerang, platform dan sistem.
awk
berfungsi dengan baik di sini tetapi dalam beberapa pengujian pada komputer saya dengan file yang sangat besar itu sekitar 30% lebih lambat daripada menggunakan grep -P
. Ini mungkin sepele dan tidak relevan berdasarkan use case, dan awk
mungkin lebih baik hanya untuk keterbacaan dan portabilitas.
Dari jawaban ini di Tanya Ubuntu:
Katakan grep untuk menggunakan ekspresi reguler seperti yang didefinisikan oleh Perl (Perl memiliki
\t
sebagai tab):grep -P "\t" <file name>
Gunakan karakter tab literal:
grep "^V<tab>" <filename>
Gunakan
printf
untuk mencetak karakter tab untuk Anda:grep "$(printf '\t')" <filename>
Salah satu caranya adalah (ini dengan Bash)
grep -P '\t'
-P
Mengaktifkan Perl ekspresi reguler sehingga \ t akan bekerja.
Sebagai pengguna bersantai mengatakan, itu mungkin khusus untuk GNU grep. Alternatifnya adalah dengan memasukkan tab di sana jika shell, editor atau terminal mengizinkannya.
Cara lain untuk menyisipkan tab secara harfiah di dalam ekspresi adalah dengan menggunakan $'\t'
kutipan yang kurang dikenal di Bash:
grep $'foo\tbar' # matches eg. 'foo<tab>bar'
(Perhatikan bahwa jika Anda cocok dengan string tetap, Anda dapat menggunakan ini dengan mode '-F'.)
Terkadang menggunakan variabel dapat membuat notasi sedikit lebih mudah dibaca dan dikelola:
tab=$'\t' # `tab=$(printf '\t')` in POSIX
id='[[:digit:]]\+'
name='[[:alpha:]_][[:alnum:]_-]*'
grep "$name$tab$id" # matches eg. `bob2<tab>323`
Ini bukan apa yang Anda cari, tetapi mungkin berhasil dalam kasus Anda
grep '[[:blank:]]'
Setara dengan
grep -P '[ \t]'
Sehingga akan menemukan Space dan Tab.
Catatan, ini tidak diiklankan di saya man grep
, tetapi masih berfungsi
$ man grep | grep blank | toilet 0 0 0
-P
argumen telah ditambahkan.
Pada dasarnya ada dua cara untuk mengatasinya:
( Disarankan ) Gunakan sintaks ekspresi reguler yang didukung oleh grep (1). Modern grep (1) mendukung dua bentuk sintaks regex POSIX 1003.2: REs dasar (usang) RE, dan RE modern . Sintaks dijelaskan secara rinci pada halaman manual re_format (7) dan regex (7) yang masing-masing merupakan bagian dari sistem BSD dan Linux. GNU grep (1) juga mendukung RE yang kompatibel dengan Perl sebagaimana disediakan oleh pustaka pcre (3).
Dalam bahasa regex, simbol tab biasanya dikodekan oleh \t
atom. Atom ini didukung oleh BSD yang berekspresi reguler yang diperluas ( egrep
, grep -E
pada sistem yang kompatibel dengan BSD), serta RE yang kompatibel dengan Perl ( pcregrep
, GNU grep -P
).
Ekspresi reguler dasar dan RE yang diperpanjang Linux tampaknya tidak memiliki dukungan untuk \t
. Silakan baca halaman utilitas UNIX untuk mengetahui bahasa regex mana yang didukungnya (karenanya perbedaan antara sed (1), awk (1), dan pcregrep (1) ekspresi reguler).
Oleh karena itu, di Linux:
$ grep -P '\t' FILE ...
Pada sistem BSD yang serupa:
$ egrep '\t' FILE ...
$ grep -E '\t' FILE ...
Masukkan karakter tab ke dalam pola. Ini mudah ketika Anda mengedit file skrip:
# no tabs for Python please!
grep -q ' ' *.py && exit 1
Namun, ketika bekerja di shell interaktif Anda mungkin perlu mengandalkan shell dan kemampuan terminal untuk mengetik simbol yang tepat ke dalam garis. Pada sebagian besar terminal, ini dapat dilakukan melalui kombinasi Ctrl
+ V
kunci yang menginstruksikan terminal untuk memperlakukan karakter input berikutnya secara harfiah ( V
untuk "verbatim"):
$ grep '<Ctrl>+<V><TAB>' FILE ...
Beberapa shell mungkin menawarkan dukungan tingkat lanjut untuk pengaturan huruf perintah. Seperti itu, dalam bash (1) kata-kata dari form $'string'
diperlakukan secara khusus:
bash$ grep $'\t' FILE ...
Harap dicatat, meskipun bersikap baik di baris perintah, ini dapat menghasilkan masalah kompatibilitas ketika skrip akan dipindahkan ke platform lain. Juga, berhati-hatilah dengan penawaran ketika menggunakan penawaran spesial, silakan berkonsultasi dengan bash (1) untuk detailnya.
Untuk shell Bourne (dan tidak hanya) perilaku yang sama dapat ditiru menggunakan substitusi perintah ditambah oleh printf (1) untuk membangun regex yang tepat:
$ grep "`printf '\t'`" FILE ...
gunakan gawk, atur pembatas bidang ke tab (\ t) dan periksa jumlah bidang. Jika lebih dari 1, maka ada tab
awk -F"\t" 'NF>1' file
awk /\t/
sudah cukup untuk pertanyaan op.
Pilihan yang baik adalah menggunakan 'sed as grep' (seperti yang dijelaskan dalam tutorial sed klasik ini ).
sed -n 's/pattern/&/p' file
Contoh (berfungsi dalam bash, sh, ksh, csh, ..):
[~]$ cat testfile
12 3
1 4 abc
xa c
a c\2
1 23
[~]$ sed -n 's/\t/&/p' testfile
xa c
a c\2
[~]$ sed -n 's/\ta\t/&/p' testfile
a c\2
Cara +1, yang bekerja di ksh, dash, dll: gunakan printf untuk memasukkan TAB:
grep "$(printf 'BEGIN\tEND')" testfile.txt
grep "$(printf '\t')" testfile.txt
Jawabannya lebih sederhana. Tulis grep Anda dan dalam kutipan ketik tombol tab, itu berfungsi dengan baik setidaknya dalam ksh
grep " " *
Menggunakan metode 'sed-as-grep', tetapi mengganti tab dengan karakter preferensi pribadi yang terlihat adalah metode favorit saya, karena ini menunjukkan dengan jelas file mana yang berisi info yang diminta, dan juga di mana ia ditempatkan dalam baris:
sed -n 's/\t/\*\*\*\*/g' file_name
Jika Anda ingin memanfaatkan informasi baris / file, atau opsi grep lainnya, tetapi juga ingin melihat penggantian yang terlihat untuk karakter tab, Anda dapat mencapainya dengan
grep -[options] -P '\t' file_name | sed 's/\t/\*\*\*\*/g'
Sebagai contoh:
$ echo "A\tB\nfoo\tbar" > test
$ grep -inH -P '\t' test | sed 's/\t/\*\*\*\*/g'
test:1:A****B
test:2:foo****bar
EDIT: Jelas di atas hanya berguna untuk melihat konten file untuk menemukan tab --- jika tujuannya adalah untuk menangani tab sebagai bagian dari sesi skrip yang lebih besar, ini tidak melayani tujuan yang bermanfaat.
Anda mungkin ingin menggunakan grep "$(echo -e '\t')"
Hanya persyaratan yang echo
harus mampu menafsirkan lolos backslash.
Metode identifikasi biner alternatif ini sepenuhnya fungsional. Dan, saya sangat suka yang menggunakan awk, karena saya tidak begitu ingat penggunaan sintaksis dengan karakter biner tunggal. Namun, itu juga harus mungkin untuk menetapkan variabel shell nilai dalam mode portabel POSIX (yaitu TAB = echo "@" | tr "\100" "\011"
), dan kemudian menggunakannya dari sana di mana-mana, dalam mode portabel POSIX; juga (mis. grep "$ TAB" nama file). Sementara solusi ini bekerja dengan baik dengan TAB, itu juga akan bekerja dengan baik karakter biner lainnya, ketika nilai biner lain yang diinginkan digunakan dalam tugas (bukan nilai untuk karakter TAB untuk 'tr').
Notasi $ '\ t' yang diberikan dalam jawaban lain khusus untuk shell - tampaknya berfungsi dalam bash dan zsh tetapi tidak universal.
CATATAN: Berikut ini untuk fish
shell dan tidak bekerja di bash :
Dalam fish
shell, seseorang dapat menggunakan tanda kutip \t
, misalnya:
grep \t foo.txt
Atau seseorang dapat menggunakan notasi hex atau unicode misalnya:
grep \X09 foo.txt
grep \U0009 foo.txt
(notasi ini berguna untuk karakter yang lebih esoteris)
Karena nilai-nilai ini harus tidak dikutip, seseorang dapat menggabungkan nilai-nilai yang dikutip dan tidak dikutip oleh gabungan:
grep "foo"\t"bar"
Anda bisa mengetik
grep \ t foo
grep 't foo
untuk mencari karakter tab di file foo. Anda mungkin juga dapat melakukan kode pelarian lainnya, meskipun saya baru menguji \ n. Meskipun agak memakan waktu, dan tidak jelas mengapa Anda ingin, di zsh Anda juga dapat mengetikkan karakter tab, kembali ke awal, ambil dan tutupi tab dengan tanda kutip.
Carilah ruang kosong berkali-kali [[: spasi:]] *
grep [[: space:]] * '.' '.'
Akan menemukan sesuatu seperti ini:
'tab' ..
Ini adalah kutipan tunggal ('), dan bukan dua kali lipat (").
Ini adalah bagaimana Anda membuat rangkaian dalam grep. = -)
grep "<Ctrl+V><TAB>"
, ini berfungsi (jika pertama kali: ketikgrep "
lalu tekan Ctrl + V key combo, lalu tekan tombol TAB, lalu ketik"
dan tekan enter, voila!)