Atama durumunda grep'in çıkmasını önleyin


29

Bu betik "after" ifadesini yankılamaz:

#!/bin/bash -e

echo "before"

echo "anything" | grep e # it would if I searched for 'y' instead

echo "after"
exit

Aynı zamanda -eshebang satırındaki seçeneği kaldırsam da olur , ancak bir hata olması durumunda betiğimin durmasını istiyorum. Grep'in bir eşleşme olmadığını hata olarak düşünmüyorum. Bu kadar aniden çıkmasını nasıl önleyebilirim?


Bu sadece değerlendirme amaçlı bir gözlemdir. Belki de bu senaryonun mantığı tekrar düşünülmeli. Dizeyi bulmak önemli değilse neden aransın? grep'in tanımı, bir dize varlığına veya yokluğuna dayanarak kararlar verecek şekildedir. Her iki şekilde de umursamıyorsan, o zaman önemli değil. Ayrıca, -eumursamanız gerektiğini düşünüyor gibi görünüyor : o kadar ki herhangi bir sorun felaket olacak.
Andrew Falanga,

2
@AndrewFalanga Her iki şekilde de önemsiyorum çünkü içeriğinin var=$(complex command | grep complex_pattern)null olabileceğini analiz ediyorum (bu durumda programım sonlandırılmamalıdır). Bu sadece problemi ortaya çıkaran kaynamış bir betiktir. Buradaki mantıkta metafiziksel karadelik yok, değil mi? ;)
iago-lito 14:17

Artık çıktıyı yakalamak istediğinizi bilmek bazı şeyleri netleştiriyor. Sunulduğu gibi, bana kafa karıştırıcıydı.
Andrew Falanga,

Yanıtlar:


33
echo "anything" | grep e || true

Açıklama:

$ echo "anything" | grep e
### error
$ echo $?
1
$ echo "anything" | grep e || true
### no error
$ echo $?
0
### DopeGhoti's "no-op" version
### (Potentially avoids spawning a process, if `true` is not a builtin):
$ echo "anything" | grep e || :
### no error
$ echo $?
0

"||" "veya" anlamına gelir. Komutun ilk kısmı "başarısız" ise ("grep e", sıfır olmayan bir çıkış kodu döndürürse), sonra "||" yürütülür, başarılı olur ve çıkış kodu olarak truesıfır döndürür ( her zaman sıfır döndürür).


3
Aynı olmayanın biraz daha kısa versiyonudur /bin/true: command || :(sizin durumunuzda, set -e; grep 'needle' haystack || :).
DopeGhoti,

1
@DopeGhoti, truebazı kabuklarda yerleşiktir (en azından bash 4.3
RHEL'de

3
Geçerli değil çünkü ilk komut başarısız olursa hatayı gizleyecektir. Borudaki ilk komut başarısız olursa doğru bir çözüm sıfırdan dönmelidir.
sorin

11

Güvenli ve isteğe bağlı olarak grep mesajlaşmanın sağlam bir yolu :

echo something | grep e || [[ $? == 1 ]] ## print 'something', $? is 0
echo something | grep x || [[ $? == 1 ]] ## no output, $? is 0
echo something | grep --wrong-arg e || [[ $? == 1 ]] ## stderr output, $? is 1

Posix el kitabına göre , çıkış kodu 1, hiçbir satır seçilmez ve> 1 bir hata anlamına gelir.


1
Bu kabul edilen cevap olmalıdır, çünkü grep bir şey bulamazsa yalnızca uyarı çıkış kodunu (1) bastırır, ancak gerçek hatalardan geçer (çıkış kodları> 1). Buradaki diğer çözümler her zaman, genellikle kötü olan gerçek hataları bastırır.
HaroldFinch

7

Başka bir seçenek boru hattına başka bir komut eklemek - başarısız olmayan bir komut:

echo "anything" | grep e | cat

Çünkü catartık boru hattı son komut, bu çıkış durumudur var cat, değil grepboru hattı başarısız olmadığını belirlemek için kullanılabilir olacağını.



3

Çözüm

#!/bin/bash -e

echo "before"

echo "anything" | grep e || : # it would if I searched for 'y' instead

echo "after"
exit

açıklama

set -e veya set -o errexit

Bir boru hattı (tek bir basit komuttan oluşabilir ), bir liste veya bir bileşik komut (yukarıya bakın SHELL GRAMMAR) sıfır olmayan bir durumdan çıkarsa hemen çıkın . Başarısız olan komut, bir whileveya untilanahtar sözcüğün hemen ardından gelen komut listesinin bir parçasıysa, ifveya elifayrılmış sözcükleri izleyen testin bir parçası , sonundaki komut dışında bir &&veya ||listedeki herhangi bir komutun bir parçası olduğunda kabuk çıkmaz&& veya ||herhangi bir boru hattında komut ancak sonuncusu veya komutun dönüş değeri ile ters çevriliyorsa!. Alt kabuk dışındaki bir bileşik komut sıfır olmayan bir durum verirse, bir komut -eyoksayılırken başarısız olduğu için kabuk çıkmaz. Bir tuzak açıksa ERR, kabuk çıkmadan önce çalıştırılır. Bu seçenek, kabuk ortamı ve her bir alt kabuk ortamı için ayrı ayrı uygulanır (yukarıya bakın COMMAND EXECUTION ENVIRONMENT) ve alt kabuktaki tüm komutları çalıştırmadan önce alt kabukların çıkmasına neden olabilir.

Artı, :Bash'deki etkisiz komuttur.

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.