Один з аргументів , що мій сценарій отримує це дата в наступному форматі: yyyymmdd
.
Я хочу перевірити, чи отримую я справжню дату як введення.
Як я можу це зробити? Я намагаюся використовувати регулярний вираз, наприклад:[0-9]\{\8}
Один з аргументів , що мій сценарій отримує це дата в наступному форматі: yyyymmdd
.
Я хочу перевірити, чи отримую я справжню дату як введення.
Як я можу це зробити? Я намагаюся використовувати регулярний вираз, наприклад:[0-9]\{\8}
Відповіді:
Ви можете використовувати тестову конструкцію [[ ]]
разом з оператором відповідності регулярних виразів =~
, щоб перевірити, чи відповідає рядок шаблону регулярного вираження .
Для вашого конкретного випадку ви можете написати:
[[ $date =~ ^[0-9]{8}$ ]] && echo "yes"
Або більш точний тест:
[[ $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
Тобто ви можете визначити регулярний вираз у Bash, який відповідає потрібному формату. Таким чином ви можете зробити:
[[ $date =~ ^regex$ ]] && echo "matched" || echo "did not match"
де команди після &&
виконуються, якщо тест успішний, і команди після ||
виконуються, якщо тест невдалий.
Зауважте, що це ґрунтується на рішенні Алекса-Даніеля Якименка у форматі перевірки формату дати введення користувачем у bash .
В інших оболонках можна використовувати греп . Якщо ваша оболонка сумісна з POSIX, зробіть це
(echo "$date" | grep -Eq ^regex$) && echo "matched" || echo "did not match"
У рибі , яка не відповідає сумісності POSIX, ви можете це зробити
echo "$date" | grep -Eq "^regex\$"; and echo "matched"; or echo "did not match"
grep
команду з -E
прапором.
sh
, fish
або інші менш обладнані раковини.
У версії 3 bash ви можете використовувати оператор '= ~':
if [[ "$date" =~ ^[0-9]{8}$ ]]; then
echo "Valid date"
else
echo "Invalid date"
fi
Довідка: http://tldp.org/LDP/abs/html/bashver3.html#REGEXMATCHREF
ПРИМІТКА: Цитування у відповідного оператора в подвійних дужках [[]] більше не потрібне для версії Bash 3.2.
Хороший спосіб перевірити, чи є рядок правильною датою, це використовувати дату команди:
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
з коментаря: можна використовувати форматування
if [ "2017-01-14" == $(date -d "2017-01-14" '+%Y-%m-%d') ]
date -d 2017-11-14e
це зробив, він повернеться вт 14 листопада 05:00:00 UTC 2017, але це зламає мій сценарій.
Я б використав expr match
замість =~
:
expr match "$date" "[0-9]\{8\}" >/dev/null && echo yes
Це краще, ніж прийнятий на даний момент відповідь використання, =~
оскільки =~
він також відповідатиме порожнім рядкам, чого IMHO не повинен. Припустимо badvar
, не визначено, то [[ "1234" =~ "$badvar" ]]; echo $?
дає (неправильно) 0
, а expr match "1234" "$badvar" >/dev/null ; echo $?
дає правильний результат 1
.
Ми повинні використовувати , >/dev/null
щоб приховати expr match
«s вихідне значення , яке число символів відповідає або 0 , якщо збігів, не знайдено. Зверніть увагу, що його вихідне значення відрізняється від статусу виходу . Стан виходу 0, якщо знайдено збіг, або 1 в іншому випадку.
Як правило, синтаксис для expr
:
expr match "$string" "$lead"
Або:
expr "$string" : "$lead"
де $lead
регулярний вираз. Її exit status
буде правдою (0), якщо lead
відповідатиме провідному фрагменту string
(Чи є для цього ім’я?). Наприклад, expr match "abcdefghi" "abc"
виходи true
, але expr match "abcdefghi" "bcd"
виходи false
. (Подяка @Carlo Wood за те, що він це вказав.
=~
не відповідає порожнім рядкам, ви порівнюєте рядок із порожнім шаблоном у наведеному прикладі. Синтаксис є string =~ pattern
, а порожній шаблон відповідає всім.
expr match "abcdefghi" "^" && echo Matched || echo No match
- і expr match "abcdefghi" "bcd" && echo Matched || echo No match
- обидва повертаються "0\nNo match"
. Де , як узгодження "a.*f"
буде повертатися "6\nMatched"
. Використання "^" у вашому прикладі також є непотрібним і вже має на увазі.
=~
відповідності порожніх рядків. Це поведінка може бути несподіваною і може спричинити помилки. Цю відповідь я написав спеціально, тому що мене спалили.
expr
погоджується зі мною.
Якщо використання регулярного вираження може бути корисним для визначення правильності послідовності символів дати, це не може бути легко використане, щоб визначити, чи дата є дійсною. Наступні приклади передадуть звичайний вираз, але всі недійсні дати: 20180231, 20190229, 20190431
Отож, якщо ви хочете перевірити, чи ваш рядок дати (назвемо його datestr
) у правильному форматі, найкраще проаналізувати його date
та попросити date
перетворити рядок у правильний формат. Якщо обидва рядки однакові, у вас є дійсний формат і дійсна дата.
if [[ "$datestr" == $(date -d "$datestr" "+%Y%m%d" 2>/dev/null) ]]; then
echo "Valid date"
else
echo "Invalid date"
fi