Bh komut dosyasında düzenli ifade


12

Bu benim ilk kez bash senaryom, bu yüzden muhtemelen kolay bir hata yapıyorum.

Temel olarak, bir kullanıcının gruplarını alır bir komut dosyası yazmaya çalışıyorum ve belirli bir grupta ise, buna göre kaydedecektir. Görünüşe göre daha fazla işlevsellik olacak, ama regex'i bile çalıştıramayacağım zaman bir nokta yok!

Şimdiye kadar, bu var:

#!/bin/bash

regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"

# example output
groups="username : username usergroup"

echo "$groups" >> /home/jrdn/log

if [[ "$groups" =~ $regex ]]; then
    echo "Match!" >> /home/jrdn/log
else
    echo "No match" >> /home/jrdn/log
fi

Bu normal ifadeyi denediğim her yerde çalışıyor. Ama bash senaryosunda, sadece çıkışını ve $groupsardından gelir No match. Birisi bana bunun neyin yanlış olduğunu söyleyebilir mi?


1
Sana bir şeylerin yanlış olduğunu düşündüren nedir?
manatwork

1
@jrdnhannah sonra yavaş yavaş hedef regexp yeniden oluşturmak deneyin, önce maç ^([a-zA-Z0-9\-_]+)sonra iki nokta üst üste eklemek ve böylece ... çok yakında öğrenmelisiniz, sorunun nerede olduğunu.
peterph

2
Bash 4.2.45 ile aynı. Alt çizgiden kaçmak düzeltildi. Tuhaf. @jrdnhannah bunu bir cevap olarak yazıp kabul edebilir misiniz lütfen?
terdon

1
Unix SE'ye yeni kaydolduğumdan, kendime cevap vermeden önce 8 saat beklemem gerekiyor. Yine de başka biri yaparsa cevap olarak işaretlemek mutlu.
jrdn

4
@terdon bash muhtemelen libc'nin normal ifade işlevlerini çağırır. Bu yüzden bash sürümüne değil, libc sürümüne bağlıdır. Cevabımı görün ... (Ya da belki de kullandığınız harmanlama sırasında bile)
derobert

Yanıtlar:


13

Gönderen man 7 regex:

Köşeli ayraç ifadesi, "[]" içine alınmış karakterlerin listesidir. ...

… Bir gerçek '-' eklemek için, onu ilk ya da son karakter yap…. [A] '\' dahil olmak üzere diğer özel karakterler, parantez ifadesi içindeki özel önemlerini kaybederler.

Normal ifadeyi egrep ile denemek hata verir:

$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end

İşte daha basit bir sürüm, bu da bir hata veriyor:

$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end

Yana \özel değil, bu sadece böyle bir aralıktır [a-z]olurdu. -Sonuna koymanız gerekir , [_-]veya gibi :

echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup

Bu, libc sürümünüzden (egrep veya bash'da) bağımsız olarak çalışmalıdır.

edit: Bu aslında yerel ayarlarınıza da bağlıdır. Manpage bu konuda uyarıyor:

Aralıklar çok harmanlama sırasına bağımlıdır ve taşınabilir programlar bunlara güvenmekten kaçınmalıdır.

Örneğin:

$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_

Tabii ki, hata yapmadıysa da, istediğinizi yapmıyor:

$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_

Bu ASCII içine alan bir dizi var \, [, ^ve _.


İlginç. Benim egrephata vermiyor, sadece doğru eşleşiyor.
manatwork

@manatwork harmanlama diziniz muhtemelen aralığa izin verir ....
derobert

Harmanlama hakkında fazla bir şey bilmiyorum. Şunu LC_COLLATE="en_US.UTF-8"mu demek istediniz ?
manatwork

@manatwork Bir örnek vermek için soruyu düzenledim. Sisteminizde farklı olabileceğini unutmayın, çünkü bazen bu harmanlama (sıralama) dizileri değişir.
derobert

1
@manatwork Tamam, kaçma girişimini fark etmeden neredeyse bir hata raporu hazırladım -...
derobert

4

Normal ifadelerle (ve daha büyük kod parçalarındaki hatalarla) genel kural: bunu kesin ve adım adım yeniden oluşturun veya ikiye ayırın - sizin için daha iyi olan her şey.

Bu durumda suçlu, alt çizgi olarak ortaya çıktı - bir ters eğik çizgiyle kaçmak onu çalıştırdı.

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.