如何抑制 bash 脚本中的错误

如何抑制 bash 脚本中的错误

我试图抑制 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

相关内容