grep perilaku aneh dengan kata-kata huruf tunggal

10

Saya menghapus kata-kata berhenti dari sebuah teks, secara kasar menggunakan kode ini

Saya punya yang berikut ini

$ cat file
file
types
extensions

$ cat stopwords
i
file
types

grep -vwFf stopwords file

Saya mengharapkan hasilnya: extensions

tapi saya mendapatkan (saya pikir salah)

file
extensions

Seolah-olah kata filetersebut telah dilewati dalam file stopwords. Sekarang inilah sedikit keren: jika saya memodifikasi file stopwords, dengan mengubah satu kata / huruf ipada baris pertama, untuk setiap huruf ascii lain selain f, i, l, e, maka perintah grep yang sama memberi saya hasil yang berbeda dan benar extensions.

Apa yang terjadi di sini dan bagaimana cara memperbaikinya?

Saya menggunakan grep (BSD grep) 2.5.1-FreeBSD pada Mac OSX GNU bash, versi 4.4.12 (1)

Tim
sumber
Anda mungkin ingin menggunakan -xsaklar untuk regex baris alih-alih -wuntuk kata? Namun saya pikir -Fsaklar akan membatalkan salah satu dari mereka, atau sebaliknya.
jesse_b
grep (GNU grep) 3.1 berfungsi seperti yang Anda harapkan.
Hauke ​​Laging
Saya telah meniru ini. Datum lain: Membuat ipola menjadi pola kedua dan bukan pola pertama dalam stopwordsfile juga mengubah perilaku.
JdeBP
Saya tidak dapat mereproduksi perilaku pada OpenBSD 6.2 dengan asli grepatau dengan GNU grep3.1.
Kusalananda

Jawaban:

13

Ini adalah bug dalam bsdgrep, berkaitan dengan variabel yang melacak bagian dari baris saat ini masih untuk memindai yang ditimpa dengan panggilan berturut-turut ke mesin pencocokan ekspresi reguler ketika beberapa pola terlibat.

perbaikan lokal

Anda dapat mengatasinya sampai batas tertentu dengan tidak menggunakan -wopsi, yang bergantung pada variabel ini untuk operasi yang benar dan karenanya gagal, tetapi sebaliknya menggunakan ekstensi ekspresi reguler yang cocok dengan awal dan akhir kata, membuat stopwordsfile Anda terlihat seperti:

\ <i \>
\ <file \>
\ <types \>

Penanganan masalah ini juga mengharuskan Anda untuk tidak menggunakan -Fopsi.

Perhatikan bahwa komponen ekspresi reguler yang terdokumentasi[[:<:]] dan [[:>:]]bahwa re_formatmanual memberi tahu Anda tentang tidak akan bekerja di sini. Ini karena pustaka ekspresi reguler yang dikompilasi menjadi bsdgrepmemiliki dukungan kompatibilitas ekspresi reguler GNU dihidupkan. Ini adalah bug lain, yang dilaporkan diperbaiki.

perbaikan layanan

Bug ini diperbaiki awal tahun ini. Perbaikan belum membuatnya menjadi rasa STABIL atau RELEASE dari FreeBSD, tetapi dilaporkan dalam CURRENT.

Untuk memasukkan ini ke versi MacOS grep, yang berasal dari FreeBSD bsdgrep, silakan berkonsultasi dengan Apple. ☺

Bacaan lebih lanjut

JdeBP
sumber
Bagus, dan terima kasih telah melaporkan hulu ini. Saya akan menemukan jawaban ini bahkan lebih menarik jika mengutip kode buggy.
Dhag
1

Kode ini:

pl " Input data file data1 and stopwords file data2:"
head data1 data2

pl " Expected output:"
cat $E

pl " Results, grep:"
# grep -vwFf stopwords file
grep -vwFf data2 data1

pl " Results, cgrep:"
cgrep -x1 -vFf data2 data1

menghasilkan:

-----
 Input data file data1 and stopwords file data2:
==> data1 <==
file
types
extensions

==> data2 <==
i
file
types

-----
 Expected output:
extensions

-----
 Results, grep:
file
extensions

-----
 Results, cgrep:
extensions

Pada sistem seperti:

OS, ker|rel, machine: Apple/BSD, Darwin 16.7.0, x86_64
Distribution        : macOS 10.12.6 (16G29), Sierra
bash GNU bash 3.2.57

Lebih detail tentang cgrep, tersedia melalui minuman, dan dari sourceforge:

cgrep   shows context of matching patterns found in files (man)
Path    : ~/executable/cgrep
Version : 8.15
Type    : Mach-O64-bitexecutablex86_64 ...)
Home    : http://sourceforge.net/projects/cgrep/ (doc)

sorakan, drl

drl
sumber
baru saja mendapat grep baru.
Tim
@Tim - Saya harap Anda menemukan cgrep bermanfaat seperti yang saya miliki. Kecepatan pada tes yang saya lakukan meletakkannya kira-kira setara dengan GNU grep, dan fitur "konteks / jendela" sangat berguna. Ini juga dibangun dengan mudah di sistem Linux ... cheers, drl
drl