在 bash LINUX 中将日期从 DD-MM-YYYY 转换为 YYYY-MM-DD 格式

在 bash LINUX 中将日期从 DD-MM-YYYY 转换为 YYYY-MM-DD 格式

设想:

我正在将文件中的日期值提取到变量中,默认情况下它采用 DD-MM-YYYY 格式。我必须从系统日期中减去这个日期。如果我的两个日期都采用 DD-MM-YYYY 格式,则减法会给出错误的结果。因此,我在谷歌上阅读了一些内容,并决定将两个日期的格式设置为 YYYY-MM-DD,因为这将在减法后给出正确的值。我已成功将系统日期格式化为 YYYY-MM-DD,但很难将从文件中获取的日期转换为 YYYY-MM-DD 格式。

以下解决方案适用于单位数字日期:

$ date -d $(sed "s/-/\//g" <<< '9-2-1832') +%Y-%m-%d
Output : 1832-09-02

但是当我尝试将日期转换为两位数时,如下所示:

$ date -d $(sed "s/-/\//g" <<< '19-07-2021') +%Y-%m-%d

我得到输出

Invalid date '19/07/2021'

在哪里:

19 - is Date of a month
07 - is Month i.e. July in this case.
2021 - is Year

所需的输出为 ->2021-07-19

我正在 RH Linux 上工作,日期版本为:date (GNU coreutils) 8.22

请帮忙提供上述问题的解决方案。

答案1

对于您的情况,awk可能是更好的方法:

$ awk -F'-' '{printf("%04d-%02d-%02d\n",$3,$2,$1)}' <<< '19-07-2021'
2021-07-19

答案2

您可以切换到 busybox date,它允许指定输入格式:

$ date=19-7-2021
$ busybox date -D %d-%m-%Y -d "$date" +%F
2021-07-19

019-007-2021(例如,请注意它不接受日期)。

与 ast-open 实现相同date(不太可能在 RedHat 系统上开箱即用):

$ date -p %d-%m-%Y -d "$date" +%F
2021-07-19

如果您使用的是 BSD 而不是 GNU 系统,您会这样做:

$ date -jf %d-%m-%Y -- "$date" +%F
2021-07-19

或者您可以切换到zsh而不是按bash原样具有内置的日期解析和格式化:

$ zmodload zsh/datetime
$ strftime -rs t %d-%m-%Y $date && strftime %F $t
2021-07-19

strftime是可以访问标准strftime()strptime()(带有-r)API 的内置函数)。

它还具有适当的分割运算符和 a printf,可以按任意顺序接受参数(使用%n$...大多数printf()实现中的语法,包括 GNU printf(),但不是printf内置的bash,也不是 GNUprintf独立实用程序),并且它不会将带有前导零的数字视为默认八进制:

$ printf '%3$04d-%2$02d-%1$01d\n' ${(s[-])date}
2021-07-19

或者使用匿名函数:

$ (){ printf '%04d-%02d-%02d\n' $3 $2 $1; } ${(s[-])date}
2021-07-19

或者这里,数组反转运算符:

$ printf '%04d-%02d-%02d\n' ${(s[-]Oa)date}
2021-07-19

答案3

如果格式硬编码为DD-YY-YYYY,您还可以硬编码整个表达式并使用子串提取重新格式化,速度非常快:

#!/bin/bash
dmy=$(date +%d-%m-%Y)
ymd="${dmy: -4}-${dmy:3:2}-${dmy:0:2}"
echo "$dmy -> $ymd"

如果格式是D[D]-M[M]-YYYY你可以使用常用表达重新格式化,这有点慢:

#!/bin/bash
dmy="9-2-1932"
if [[ "$dmy" =~ ^([[:digit:]]+)-([[:digit:]]+)-([[:digit:]]+)$ ]] ; then
  ymd="${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]}"
fi
echo "$dmy -> $ymd"

您可以使用以下格式更好一点printf:

dmy="9-02-2032"
if [[ "$dmy" =~ ^([[:digit:]]+)-([[:digit:]]+)-([[:digit:]]+)$ ]] ; then
  printf -v ymd '%.4d-%.2d-%.2d' \
    "${BASH_REMATCH[3]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[1]}"
fi
echo "$dmy -> $ymd"

这个答案的前一个版本证明我没有完全阅读它,转换YYYY-MM-DDDD-MM-YYYY

#!/bin/bash

ymd=$(date  +%Y-%m-%d)
dmy="${ymd: -2}-${ymd:5:2}-${ymd:0:4}"
echo "$ymd -> $dmy"

答案4

仅使用 sed 的快速而精益的解决方案:

echo 19-07-2021 | sed -E 's/^([0-9]{1,2})-([0-9]{1,2})-([0-9]{4})$/\3-\2-\1/'

相关内容