Grep'deki yıldız işaretini kullanma


90

Linux / bash içindeki belirli bir dosyada "abc" alt dizesini aramaya çalışıyorum

Ben de yapıyorum:

grep '*abc*' myFile

Hiçbir şey döndürmez.

Ama yaparsam:

grep 'abc' myFile

Eşleşmeleri doğru şekilde döndürür.

Şimdi, bu benim için sorun değil. Ama ya daha karmaşık bir dizge için grep yapmak istersem

*abc * def *

Grep kullanarak bunu nasıl başarabilirim?


3
grep'in kendisi çoğu platformda joker karakterleri desteklemez. Joker karakter kullanmak için egrep kullanmanız gerekir. Kabukların farklı bir sözdizimi vardır. Kabuktaki "*" <herhangi bir dizedir>. Egrep'te "önceki varlıkların çoğuna 0" yazan bir operatördür. Grep'te, bu sadece normal bir karakter.
PanCrit

@PanCrit: *grep ve egrep'te aynı anlama gelir: Bu , önceki atomun sıfır veya daha fazlası anlamına gelen bir niceleyici . Bu , kabuğun kullandığı joker karakterlerden tamamen farklı bir kavram .
Alan Moore

Yanıtlar:


124

Yıldız işareti yalnızca bir tekrar operatörüdür , ancak neyi tekrarladığınızı ona söylemeniz gerekir. /*abc*/ab ve sıfır veya daha fazla c içeren bir dizeyle eşleşir (çünkü ikinci * c'nin üzerindedir; birincisi anlamsızdır çünkü tekrar edecek bir şey yoktur). Herhangi bir şeyi eşleştirmek istiyorsanız, şunu söylemelisiniz .*- nokta herhangi bir karakter anlamına gelir ( belirli kurallar dahilinde ). Sadece abc ile eşleşmek istiyorsanız, diyebilirsiniz grep 'abc' myFile. Daha karmaşık eşleşmeniz için .*- kullanmanız gerekir - grep 'abc.*def' myFileabc ve ardından def içeren bir dizeyi isteğe bağlı olarak arada bir şeyle eşleştirir.

Bir yoruma göre güncelleme:

*Normal ifadede, konsoldaki * ile tam olarak aynı değildir. Konsolda *, bir glob yapısının parçasıdır ve yalnızca bir joker karakter görevi görür (örneğin ls *.log, .log ile biten tüm dosyaları listeler). Ancak, normal ifadelerde * bir değiştiricidir, yani yalnızca kendisinden önceki karakter veya grup için geçerli olduğu anlamına gelir. Normal ifadelerde * 'nin joker karakter olarak davranmasını istiyorsanız .*, daha önce belirtildiği gibi kullanmanız gerekir - nokta bir joker karakterdir ve noktayı değiştirirken yıldız, bir veya daha fazla nokta bulmak anlamına gelir; yani. herhangi bir karakterden bir veya daha fazlasını bulun.


1
Sanırım soru soran kişi, kabuk joker karakterleri ile normal ifadeler arasındaki fark konusunda kafası karışık. Ayrıca daha karmaşık ifadenin şu olacağından şüpheleniyorum: grep 'abc. * Def' (en az bir boşluk mevcut - muhtemelen yazdığım gibi iki).
Jonathan Leffler

1
Aslında, soruyu soran kişi 'abc'nin' ^ abc $ 'ile aynı şey olmadığını anlamıyor gibi görünüyor :-D
Massa

1
Evet, glob ve tam düzenli ifadeler arasında kafam karışmıştı. Kabuktaki herhangi bir şeyi eşleştirmek için * noktasız olarak kullanıyorum.
Saobi

1
grep *"0 veya daha fazla" anlamına gelir ve grep varsayılan olarak açgözlüdür. Grep o Not temel düzenli ifadeler meta karakterleri ?, +, {, |, (, ve )onların özel bir anlamı kaybederler. Daha fazla bilgi: grep
regexps

25

Nokta karakteri, herhangi bir karakterle eşleştiği anlamına gelir, yani herhangi bir karakterin .*sıfır veya daha fazla oluşumu anlamına gelir. Muhtemelen .*sadece kullanmak yerine kullanmayı kastediyorsunuz *.


Nokta, yeni satırlar dışında herhangi bir karakteri kabul eden bir meta karakterdir .
Abhishek Kamal

12

"Yıldız işareti" sadece önünde bir şey varsa anlamlıdır. Araç yoksa (bu durumda grep) onu bir hata olarak değerlendirebilir. Örneğin:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz

5
* Anlamsız değildir; (tekrarın) olağan anlamı yoktur, ancak "Ben bir yıldızım" anlamına gelir. Bir yıldızın ardından x, y ve z içeren bir çizgiyle eşleşir.
Jonathan Leffler

2
@Jonathan Bu araca bağlıdır.

9

Perl tarzı normal ifadeler için destek sağlayan grep -P'yi kullanın.

grep -P "abc.*def" myfile

6

Denediğiniz ifadeye, örneğin Linux'ta kabuk komut satırında çalışanlar gibi, " glob " denir . Glob ifadeleri tam düzenli ifadeler değildir , grep bunu aranacak dizeleri belirtmek için kullanır. İşte farklılıklar hakkında (eski, küçük) yazı. Glob ifadeleri ("ls *" gibi) kabuğun kendisi tarafından yorumlanır.

Glob'lardan RE'lere çeviri yapmak mümkündür, ancak genellikle bunu kafanızda yapmanız gerekir.


1
Sadece kabuk tarafından ayrıştırılırsa bir küre. Arama dizgisini tek tırnak içinde koruduğu için, kabuk dizgeyi tek başına bırakır ve argv'de grep'e dokunmadan geçirir.
Göze Çarpan Derleyici

4

Normal ifadeler kullanmıyorsunuz, bu nedenle, grep seçeneğiniz fgrep, beklediğiniz gibi davranacak şekilde olmalıdır.


2
fgrepartık kullanımdan kaldırıldı, grep -fbunun yerine kullanılmalı.
Prometheus

1
Bu "grep -F". İyi ol 'fgrep "kullanımdan kaldırılmış" olabilir, ama ben hala hayattayken onu geri almayacaklar.
Andrew Beals


1

Aradığınız cevap bu olabilir:

grep abc MyFile | grep def

Tek sorun şu ki ... "def" satırları "abc" den önce VEYA sonradır


1

Bu benim için çalıştı:

grep ". * $ {ifade}" - çift tırnak işaretleriyle, başında nokta. Burada "ifade", satırın sonunda ihtiyacınız olan dizedir.

Ek anahtarlar olmadan standart unix grep.


0

'*' önceki öğe için değiştirici olarak çalışır. Bu nedenle, 'abc * def', 'ab' için arama yapar ve ardından 0 veya daha fazla 'c,' def 'ile gelir.

Muhtemelen istediğiniz şey, "abc" yi arayan "abc. * Def" ve ardından herhangi bir sayıda karakter gelir ve ardından "def" gelir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.