Bir bash betiğinde düzenli ifadelerle bir testi nasıl reddederim?


174

GNU bash (sürüm 4.0.35 (1) -release (x86_64-suse-linux-gnu) kullanarak, Normal İfadeler ile bir testi reddetmek istiyorum, örneğin, koşullu olarak PATH değişkenine bir yol eklemek istiyorum, yol zaten orada değilse, aşağıdaki gibi:

TEMP=/mnt/silo/bin
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/Scripts:
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/local/bin
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi
export PATH

Eminim bunu yapmanın bir milyon yolu vardır, ama bilmek istediğim, koşullu bir şekilde (hatalı) olduğu gibi bir şekilde reddedilebilirse:

TEMP=/mnt/silo/bin
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/Scripts:
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi
TEMP=/mnt/silo/local/bin
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi
export PATH

Yanıtlar:


194

Haklıydın, sadece !ve [[benzerleri arasına bir boşluk koyif ! [[


14
Oye vey! Perga'nın galaksiler arası özel karakter deliliğini güvenle kaldırdığımda, kendimi bash alanında (yerleştirme) kaybettiğimi düşünüyorum! (Bağırsaklarımı bir piton gibi sıkmaktan korkuyorum.) Teşekkürler!
David Rogers

127

Ünlem işaretini parantez içine de koyabilirsiniz:

if [[ ! $PATH =~ $temp ]]

ancak yanlış pozitifleri azaltmak için deseninizi sabitlemelisiniz:

temp=/mnt/silo/bin
pattern="(^|:)${temp}(:|$)"
if [[ ! "${PATH}" =~ ${pattern} ]]

başında veya sonunda iki nokta üst üste (veya her ikisi) olan bir eşleşme arar. Kabuk değişkenlerle ad çakışması olasılığını azaltmak için alışkanlık olarak küçük harfli veya karma büyük harf değişken adlarını kullanmanızı öneririm.


Ah, demirlemeyle ilgili hatırlatma için teşekkürler. Küçük veya karışık değişken adları kullanma fikri bir bash acemi için kafa karıştırıcıdır, çünkü şimdiye kadar gördüğüm tavsiye büyük harf kullanmaktır. Yaptığınız noktayı anlıyorum, ancak yemek kitabından (anlayışımı) sapmak için rahat hissetmek için yeterince bash komut dosyası örnekleri görmedim.
David Rogers

4
@ herkes bu konuda bize güveniyor. Kullanıcı tanımlı büyük harf değişkenlerinden kaçınılmalıdır. Bash içindeki tüm değişkenler ile genişletilir, $bu yüzden onları öne çıkarmak için büyük harf kullanmanın bir nedeni yoktur.
SiegeX

Ben if [[ ! $foo =~ bar ]]daha güvenli buluyorum if ! [[ $foo =~ bar ]], çünkü daha fazla koşul tanıtmak kolaylaştırırif
CTodea

19

en güvenli yolu koymaktır! bunun içindeki normal ifade olumsuzlaması için [[ ]]:

if [[ ! ${STR} =~ YOUR_REGEX ]]; then

aksi takdirde bazı sistemlerde başarısız olabilir.


9

Evet, SiegeX'in işaret ettiği gibi testi reddedebilirsiniz .

Ancak bunun için düzenli ifadeler kullanmamalısınız - yolunuz özel karakterler içeriyorsa başarısız olabilir. Bunun yerine şunu deneyin:

[[ ":$PATH:" != *":$1:"* ]]

(Kaynak)


1
Bu formu kullanmanın başka bir nedeni, alt dizeleri yanlışlıkla eşleştirmemesidir (örneğin, yola "/ bin" eklenemediği için "/ usr / bin" zaten var).
Gordon Davisson

Soldaki kolonların bana istediğim bağlantıyı nasıl verdiğini anlamak biraz zamanımı aldı. aranacak olan dizeye malzeme ekleyerek kalıbı azaltma fikri hatırlamaya değer. Yoldaki özel karakterlerin neden regex çözümünü bozacağını anlamıyorum ama bash çözümünü değil. Bana bir örnek verebilirmisin?
David Rogers

Bunun her durumda güvenilir bir şekilde çalışacağını düşünmüyorum. Üstün IMHO'da Regex Eşleşmesi
Felipe Alvarez

5

Bu gibi durumlarda koşullu işleçleri kullanmadan kodu basitleştirmek isterim:

TEMP=/mnt/silo/bin
[[ ${PATH} =~ ${TEMP} ]] || PATH=$PATH:$TEMP
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.