Grep true / false döndürür mü yoksa alternatif yöntemler var mıdır?


130

Bu betiğin bir parçası olarak, verilen ilk argümanın ilk dosya kelimesiyle uyuşup uyuşmadığını kontrol etmem gerekiyor. Varsa, bir hata mesajı ile çıkın; değilse, argümanları dosyaya ekleyin. İfadenin nasıl yazıldığını anlıyorum ifama grepbir senaryoda nasıl kullanılacağını anlayamadım . Bunun grepböyle bir şeye benzeyeceğini biliyorum

grep ^$1 schemas.txt

Bunun yaptığımdan daha kolay olması gerektiğini düşünüyorum.

Açıklamada "çok fazla tartışma" hatası alıyorum if. Aradaki boşluktan kurtuldum grep -qve sonra ikili bir operatörün beklediği bir hata aldım.

if [ grep -q ^$1 schemas.txt ]
then
        echo "Schema already exists. Please try again"
        exit 1
else
        echo "$@" >> schemas.txt
fi

1
Lose []ve işe yarayacak. Muhtemelen kalıbınızı alıntılamak istemenize rağmen:if grep -q "^$1" schemas.txt; then …
derobert

Bash'in "Grup Komutanlığı" özelliğini kullanan bir satırlık çözüm: stackoverflow.com/questions/6550484/…
Trevor Boyd Smith

Yanıtlar:


186

grepeğer bir şey bulamadıysa (sıfır) farklı bir çıkış kodu döndürür. Bir ififadede, sıfır çıkış kodu "true" olarak eşlenir ve sıfır olmayan bir çıkış kodu false olarak eşlenir. Ek olarak, grep -qeşleştirilen metni çıkarmamak için bir argümana sahiptir (ancak yalnızca çıkış durum kodunu döndürür)

Yani, grep'i şu şekilde kullanabilirsiniz:

if grep -q PATTERN file.txt; then
    echo found
else
    echo not found
fi

Kısa bir not gibi if [ -z "$var" ]…, böyle bir şey yaptığınızda [, aslında grep gibi çalıştırdığınız bir komut olduğu anlaşılıyor . Benim sistemimde öyle /usr/bin/[. (Eh, teknik olarak, kabuğunuzun içinde yerleşik bir yapı vardır, ancak bu bir optimizasyondur. Bir komut gibi davranır). Aynı şekilde çalışır, [true için sıfır çıkış kodu, false için sıfır olmayan çıkış kodu döndürür. ( kapanış hariç test, aynı şey )[]


Neden if ifadesinde parantez gerekmiyor? Onsuz çalışmasını sağladım, ama nedenini anlamadım. Hala parantez olmadan iç içe geçebilir miyim?
Lauren

@Lauren kısa notu özledin mi? [if sözdiziminin bir parçası değildir, (kavramsal olarak) koştuğunuz bir komuttur, tıpkı grep gibi
derobert

2
@Lauren Hangi koşulu kontrol etmek istediğinize bağlı olarak, [, birini ya da diğerini kullanırsınız. (Eğer bir çıkış kodu varsa if, btw içindeki herhangi bir komutu kullanabilirsiniz.)… Peki, sanırım içinde grep kullanmak için bir neden bulabilirdiniz [, ama bu oldukça karmaşık bir komut dosyası ve yapılacak normal bir şey değil.
derobert 18:12

3
Bilginize, koşun ls -l /usr/bin/\[ve man [bunun [başka bir program olduğunu görünce, sadece sözdizimsel bir öğeye benziyor - bu açık ve anlaşılır hale getirmeli. (kolaylık olması için, [aynı zamanda bir bash, dash ve diğerleri de yerleşiktir - ama yine de bir komuttur). ayrıca type -all [bash içinde deneyin .
cas

1
@AlexanderCska, eşlenen çizgilerin yazdırılmasını istiyorsanız (örneğin, onları bir yere yerleştirmek için), ardından -q, bu seçeneğin, eşleştirmenin sessiz olmasını söylediğini (eşleşen çizgileri yazdırmaz) söyleyin.
derobert

47

Diğer bir basit yol kullanmaktır grep -c.

Çıktı (çıkış kodu olarak geri dönmez), modelle eşleşen satır sayısı, eşleşme yoksa 0, eşleşme varsa 1 veya daha fazla çıktı.

Yani, kalıbın 3 veya daha fazla kez eşleştirildiğini kontrol etmek isteseniz, şunları yaparsınız:

if [ "$(grep -c "^$1" schemas.txt)" -ge 3 ]; then
  ...

17
Daha doğrusu, o olacak çıkış sadece bir kez 1 bulursa. 1 çıktısını almak için bulunan eşleşmelerin miktarına bakılmaksızın grep -cim1bunun yerine kullanın.
Manatwork

Bu yöntem, grep hatası ile grep '0 kez bulunan kalıp' arasındaki farkı ayırt etmek için de kullanılabilir. (kullanılan ifadenin tam olmasa da, bir değişkenin gerekli olduğunu düşünüyorum)
Evan Benn

3

Buna geç kaldığımı biliyorum, ancak bu kısa halini seviyorum:

grep -q ^$1 schemas.txt && echo "Schema already exists. Please try again" || echo "$@" >> schemas.txt

0

Eğer bir dosyanın ilk kelimesini yakalamak istiyorsak -zwgrep'a eklememiz gerekir

if grep -qzw "^$1" file
then 
   ... 
else 
   ... 
fi

-zBir satırın ilk kelimesini bile almadan . -wKısmi kelimeler olmadan .


-2

Köşeli parantez ile kullanmak istiyorsanız, aşağıdakileri

if [ `grep -q PATTERN file.txt` ]; then
    echo found
else
    echo not found

Bu Mantık tüm komutlar için çalışır, Sadece komutlarınızı backtick'in içine yerleştirin (yukarıdaki sekme veya Esc düğmesinin aşağı veya 1 düğmesinin soluna)


1
`grep -q PATTERN file.txt`Aksi halde alıntı yapmanız gerekir , aksi takdirde split + glob işleci uygulanır ve karakter $IFSveya joker karakter içeren herhangi bir çıktı için soruna neden olur . Daha genel olarak, stdout'taki en az bir boş olmayan satır çıktısı olursa (NUL byte'lar çıkması durumunda olası problemlerle) [ "`cmd`" ]doğru döner cmd. Bu, kabuğun tüm çıktının bellekte saklanması ve bitmesini beklemesi gerektiği anlamına gelir. Kullanılması if cmd | grep -q .yerine bu konuda tercih edilebilir.
Stéphane Chazelas

Bu komut hiç bir anlam ifade etmiyordu. -qAnahtarın amacı, çıktısını bastırmaktır grep . Söylediğiniz: file.txt dosyasındaki PATTERN öğesini kontrol edin, herhangi bir çıktıyı bastırın, ardından PATTERN öğesinin bulunup bulunmadığına göre dönüş durumunu ayarlayın. Daha sonra, geri dönüş durumunu yoksayın , (boş olmaya zorladığımız) komut çıktısını alın, sözcük bölme ve dosya glob genişlemesi uygulayın (hiç tartışma olmadan sonuçlanır), ardından [(aka test) komutunu tam bir argümanla çalıştırın - yani , - ve ]sonra, bu bir hataya neden olacağından, yankı "bulunamadı". @ StéphaneChazelas, bir şey mi kaçırdım?
Joker

1
@Wildcard, haklısın, görünüşe göre gözardı ettim -q. PATTERN yalnızca boş satırlarla eşleşebilirse [ `grep PATTERN file.txt ` ]bu yorum anlamlı olurdu , ancak yorumda [ "`grep -n PATTERN file.txt`" ]belirtildiği gibi daha iyi olurdu. Tabii ki burada elbette if grep -q PATTERN file.txtistiyorsun.
Stéphane Chazelas
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.