Benim senaryom aldığı bağımsız değişkenlerden biri aşağıdaki biçimde bir tarihtir: yyyymmdd
.
Giriş olarak geçerli bir tarih alıp almadığımı kontrol etmek istiyorum.
Bunu nasıl yapabilirim? Ben gibi bir regex kullanmaya çalışıyorum:[0-9]\{\8}
Benim senaryom aldığı bağımsız değişkenlerden biri aşağıdaki biçimde bir tarihtir: yyyymmdd
.
Giriş olarak geçerli bir tarih alıp almadığımı kontrol etmek istiyorum.
Bunu nasıl yapabilirim? Ben gibi bir regex kullanmaya çalışıyorum:[0-9]\{\8}
Yanıtlar:
Dizenin [[ ]]
normal ifade eşleme işleciyle birlikte =~
bir dizenin normal ifade modeliyle eşleşip eşleşmediğini kontrol etmek için test yapısını kullanabilirsiniz .
Özel durumunuz için şunları yazabilirsiniz:
[[ $date =~ ^[0-9]{8}$ ]] && echo "yes"
Veya daha doğru bir test:
[[ $date =~ ^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$ ]] && echo "yes"
# |^^^^^^^^ ^^^^^^ ^^^^^^ ^^^^^^ ^^^^^^^^^^ ^^^^^^ |
# | | ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ |
# | | | | |
# | | \ | |
# | --year-- --month-- --day-- |
# | either 01...09 either 01..09 end of line
# start of line or 10,11,12 or 10..29
# or 30, 31
Yani bir regex tanımlayabilir olan Bash istediğiniz biçimiyle eşleşen. Bu şekilde şunları yapabilirsiniz:
[[ $date =~ ^regex$ ]] && echo "matched" || echo "did not match"
burada &&
test başarılı ||
olursa sonraki komutlar yürütülür ve test başarısız olursa sonraki komutlar yürütülür.
Bunun, Aleks-Daniel Jakimenko'nun Kullanıcı giriş tarihi biçim doğrulamasındaki bash çözümüne dayandığını unutmayın .
Diğer mermilerde grep kullanabilirsiniz . Kabuğunuz POSIX uyumluysa,
(echo "$date" | grep -Eq ^regex$) && echo "matched" || echo "did not match"
In balık POSIX uyumlu değil, yapabileceğiniz
echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"
grep
komuttan daha kolay anlayacağından eminim -E
.
sh
, fish
ya da diğer daha az donanımlı kabukları.
Bash sürüm 3'te '= ~' operatörünü kullanabilirsiniz:
if [[ "$date" =~ ^[0-9]{8}$ ]]; then
echo "Valid date"
else
echo "Invalid date"
fi
Referans: http://tldp.org/LDP/abs/html/bashver3.html#REGEXMATCHREF
NOT: Çift parantez içindeki [[]] eşleşen işleçteki alıntı artık Bash sürüm 3.2'den itibaren gerekli değildir
Bir dizenin doğru tarih olup olmadığını test etmenin iyi bir yolu komut tarihini kullanmaktır:
if date -d "${DATE}" >/dev/null 2>&1
then
# do what you need to do with your date
else
echo "${DATE} incorrect date" >&2
exit 1
fi
Yorumdan: biçimlendirmeyi kullanabilirsiniz
if [ "2017-01-14" == $(date -d "2017-01-14" '+%Y-%m-%d') ]
date -d 2017-11-14e
14 Kasım 05:00:00 UTC 2017 döndürür, ancak bu benim komutumu kıracak.
Bunun expr match
yerine kullanmak istiyorum =~
:
expr match "$date" "[0-9]\{8\}" >/dev/null && echo yes
Bu, şu anda kabul edilen kullanım cevabından daha iyidir, =~
çünkü =~
IMHO'nun yapmaması gereken boş dizelerle de eşleşecektir. Varsayalım badvar
tanımlanmamıştır, daha sonra [[ "1234" =~ "$badvar" ]]; echo $?
(yanlış) verir 0
iken, expr match "1234" "$badvar" >/dev/null ; echo $?
doğru bir sonuç verir 1
.
Biz kullanmak zorunda >/dev/null
gizlemek için expr match
'ın çıkış değeri eşleşme bulursa karakter sayısı eşleşti veya 0,. Çıkış değerinin çıkış durumundan farklı olduğunu unutmayın . Bir eşleşme bulunursa çıkış durumu 0 veya aksi takdirde 1 olur.
Genellikle, söz dizimi expr
:
expr match "$string" "$lead"
Veya:
expr "$string" : "$lead"
$lead
düzenli bir ifade nerede . (Bunun için bir isim var mı?) Öğesinin önde gelen dilimi ile eşleşirse, exit status
true (0) olur . Örneğin çıkışlar , çıkışlar . (Bunu işaret ettiği için @Carlo Wood'a teşekkür ederiz.lead
string
expr match "abcdefghi" "abc"
true
expr match "abcdefghi" "bcd"
false
=~
boş dizelerle eşleşmiyorsa, bir dizeyi verdiğiniz örnekteki boş bir desenle eşleştiriyorsunuz . Sözdizimi string =~ pattern
ve boş bir kalıp her şeyle eşleşir.
expr match "abcdefghi" "^" && echo Matched || echo No match
- ve expr match "abcdefghi" "bcd" && echo Matched || echo No match
- ikisi de geri döner "0\nNo match"
. Eşleme olarak "a.*f"
geri dönülecek "6\nMatched"
. Örneğinizde '^' kullanımı da gereksizdir ve zaten ima edilmiştir.
=~
boş dizeleri eşleştirme davranışını rasyonelleştirip birleştiremeyeceği değildir . Bu davranış beklenmedik olabilir ve hatalara neden olabilir. Bu yanıtı özellikle yazdım çünkü yanmıştım.
expr
benimle aynı fikirde.
Normal ifadenin kullanımının, bir tarihin karakter dizisinin doğru olup olmadığını belirlemeye yardımcı olabileceği durumlarda, tarihin geçerli olup olmadığını belirlemek için kolayca kullanılamaz. Aşağıdaki örnekler normal ifadeyi geçecek, ancak tümü geçersiz tarihlerdir: 20180231, 20190229, 20190431
Bu nedenle, tarih dizenizin (diyelim datestr
) doğru biçimde olup olmadığını doğrulamak istiyorsanız , onu ayrıştırmak date
ve date
dizeyi doğru biçime dönüştürmek istemek en iyisidir . Her iki dize de aynıysa, geçerli bir biçiminiz ve geçerli bir tarihiniz vardır.
if [[ "$datestr" == $(date -d "$datestr" "+%Y%m%d" 2>/dev/null) ]]; then
echo "Valid date"
else
echo "Invalid date"
fi