我试图抑制 date 命令生成的错误,但执行脚本后仍然出现错误。
#!/usr/bin/bash
input="30 FEB 2022"
reg="^[0-9]{1,2}\s[a-zA-Z]{1,3}\s[0-9]{1,4}$"
if [[ $input =~ $reg ]]
then
echo "VALID Date Format : $input"
#output=$(`date -d "$input" +"%d-%b-%Y, %A"` 2>&1 > /dev/null)
output=`date -d "$input" +"%d-%b-%Y, %A"` 2>&1 > /dev/null
else
echo "INVALID Date Format : $input"
output="-1"
fi
echo $output
执行后输出 -
root@ip-xx-x-xx-xxx:~# ./exDate.sh
VALID Date Format : 30 FEB 2022
date: invalid date '30 FEB 2022'
请告知我如何抑制错误?
答案1
您已经得到了答案,为您提供了更好的方法,所以我只回答您提出的问题。您仍然看到错误消息的原因是重定向的顺序很重要。重定向是从左到右读取的,因此2>&1 > /dev/null
意味着“首先将 stderr 重定向到 stdout,然后然后将 stdout 重定向到/dev/null
“。这意味着您的错误将被打印到 stdout,并且正常的 stdout 正在被重定向到/dev/null
。您可以通过将 stdout 管道传输到 来看到这一点wc
:
## No redirection
$ date -d foo
date: invalid date ‘foo’
## Nothing is printed to stdout, the error goes to stderr
## and wc has nothing to count
$ date -d foo | wc
date: invalid date ‘foo’
0 0 0
## Redirect using 2>&1 > /dev/null
$ date -d foo 2>&1 > /dev/null
date: invalid date ‘foo’
## The error is now being printed to stdout, wc counts it
$ date -d foo 2>&1 > /dev/null | wc
1 4 29
你想要的是将标准输出重定向到/dev/null
第一个和然后将 stderr 重定向到 stdout: > /dev/null 2>&1
。这行为如您所愿:
$ date -d foo > /dev/null 2>&1
$
答案2
您无法使用正则表达式或模式验证日期。 (好吧,我想你也许可以这样做,但那会很不愉快。)
相反,使用date
命令本身来验证输入。将此脚本写入文件exDate
并使其可执行 ( chmod a+x exDate
):
#!/bin/bash
input=$1
if date --date "$input" >/dev/null 2>&1
then
# Good date
output=$(date --date "$input" +'%d-%b-%Y, %A')
else
# Date parsing failed
printf 'INVALID Date Format : %s\n' "$input" >&2
output='-1'
fi
printf "%s\n" "$output"
运行示例
./exDate '30 FEB 2022'
INVALID Date Format : 30 FEB 2022
-1
./exDate '24 FEB 2022'
24-Feb-2022, Thursday
./exDate '2022-04-13'
13-Apr-2022, Wednesday
如果最后一个选项不可接受(即您只想接受表单中的日期d(d) MMM yyyy
),那么您将需要模式匹配以及使用date
来验证:
if [[ "$input" =~ ^[0-9]{1,2}\ [a-zA-Z]{3}\ [0-9]{4}$ ]] && date…
then
您可以将if date...
与output=
分配合并,从而简化代码,然后只需要处理失败情况:
if ! output=$(date --date "$input" +'%d-%b-%Y, %A' 2>/dev/null)
then
# Date parsing failed
printf 'INVALID Date Format : %s\n' "$input" >&2
output='-1'
fi
答案3
默认输入日期格式为美国。月份必须在日期之前。
$ date -d '02/02/2022'
Wed 02 Feb 2022 12:00:00 AM UTC
$ date -d '02/22/2022'
Wed 22 Feb 2022 12:00:00 AM UTC
是的,月份可以用字母表示(FEB 或 feb,即使区域设置在另一个国家/地区)
$ date -d 'FEB 22 2022'
Tue 22 feb 2022 00:00:00 UTC
$ ( LC_ALL=es_ES.utf8 date -d 'FEB 22 2022')
mar 22 feb 2022 00:00:00 UTC
$ ( LC_ALL=ja_JP.utf8 date -d 'FEB 22 2022')
2022年 2月 22日 火曜日 00:00:00 UTC
但是,任何日期都不可能不是如果给定日期尝试报告错误不存在。 2 月 30 日并不存在。在这种情况下,没有日期输出。并且,它将退出状态设置为 1。我们实际上可以使用它来验证输入日期,而不需要正则表达式:
#!/bin/bash
input="${1:-"30 FEB 2022"}"
if output=`date -d "$input" +"%d-%b-%Y, %A" 2>&1`
then echo "VALID Date : $input"
else echo "INVALID Date : $input"
output="-1"
fi
printf '%s\n' "$output"
当然,重定向必须在`...`
让他们工作。
$ ./exDate.sh
INVALID Date : 30 FEB 2022
-1
$ ./exDate.sh "22 FEB 2022"
INVALID Date : 22 FEB 2022
-1
$ ./exDate.sh "FEB 22 2022"
VALID Date : FEB 22 2022
22-Feb-2022, Tuesday
$ ./exDate.sh "FEB 30 2022"
INVALID Date : FEB 30 2022