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"
grepkomuttan daha kolay anlayacağından eminim -E.
sh, fishya 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-14e14 Kasım 05:00:00 UTC 2017 döndürür, ancak bu benim komutumu kıracak.
Bunun expr matchyerine 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 badvartanımlanmamıştır, daha sonra [[ "1234" =~ "$badvar" ]]; echo $?(yanlış) verir 0iken, expr match "1234" "$badvar" >/dev/null ; echo $?doğru bir sonuç verir 1.
Biz kullanmak zorunda >/dev/nullgizlemek 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"
$leaddüzenli bir ifade nerede . (Bunun için bir isim var mı?) Öğesinin önde gelen dilimi ile eşleşirse, exit statustrue (0) olur . Örneğin çıkışlar , çıkışlar . (Bunu işaret ettiği için @Carlo Wood'a teşekkür ederiz.leadstringexpr match "abcdefghi" "abc"trueexpr match "abcdefghi" "bcd"false
=~boş dizelerle eşleşmiyorsa, bir dizeyi verdiğiniz örnekteki boş bir desenle eşleştiriyorsunuz . Sözdizimi string =~ patternve 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.
exprbenimle 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 dateve datedizeyi 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