首页 > 解决方案 > 如何在 Shell 脚本中将日期格式 MM-DD-YY HH:MI AM/PM 转换为 YYYY-MM-DD

问题描述

我目前正在尝试使用以下命令转换日期格式

while IFS=$'\t' read -r -a ValArray
do
FILEDATE=${ValArray[0]}
COMPDATE=`date -d  $FILEDATE +'%Y-%m-%d'`

尝试从文件中动态获取值并将其与今天的日期进行比较时出现以下错误

++ read -r -a ValArray
++ FILEDATE='02-11-20 2:25 AM'
+++ date -d 02-11-20 2:25 AM +%Y-%m-%d
date: extra operand `AM'
Try `date --help' for more information.

如何覆盖它并以 YYYY-MM-DD 格式获取日期?

标签: shelldateunix

解决方案


使用参数扩展

POSIX shell 提供参数扩展来从字符串的左(前)或右(后)的开头删除substringa string

${string#substring}     Strip shortest match of $substring from front of $string
${string##substring}    Strip longest match of $substring from front of $string
${string%substring}     Strip shortest match of $substring from back of $string
${string%%substring}    Strip longest match of $substring from back of $string

子字符串可以包含正常的文件通配符,例如'*','?'等。

在您的情况下(使用f='02-11-20 2:25 AM'),您可以从左右删除各种子字符串以获得月、日和年。然后,您可以将 2 位数的年份乘以100得到 4 位数的年份,如下所示:

f='02-11-20 2:25 AM'
f="${f% *}"     # trim AM (to first space) from right (back)
f="${f% *}"     # trim 2:25 (to first space) from right
m="${f%%-*}"    # trim to last - from right leaving month
y="${f##*-}"    # trim to last - from left (front) leaving year
d="${f#*-}"     # trim to first - from left leaving day-year
d="${d%-*}"     # trim to first - from right leaving day
y=$((y*100))    # mulitply 2-digit year by 100
printf "%4d-%02d-%02d\n" "$y" "$m" "$d"     # output in desired format

使用expr substr string start length

POSIX 还提供了旧expr ....的字符串操作函数集,但由于涉及命令替换,它可能会比内置参数扩展慢。这里相关的是:

expr substr string start length

从索引 (1-based) 开始提取length字符子字符串。您可以使用以下方法检索月、日和年:stringstart

f='02-11-20 2:25 AM'
m=$(expr substr "$f" 1 2)                   # extract 2-digit substring at 1
d=$(expr substr "$f" 4 2)                   # extract 2-digit substring at 4
y=$(expr substr "$f" 7 2)                   # extract 2-digit substring at 7
y=$((y*100))                                # mulitply 2-digit year by 100
printf "%4d-%02d-%02d\n" "$y" "$m" "$d"     # output in desired format

注意:就像使用时[...]总是引用你的变量一样expr ...

使用sed

您还可以使用sed具有三个捕获组和三个反向引用的基本替换来以正确的顺序重新插入日期组件。捕获组\(text\)捕获它们之间的文本(由正则表达式表示 text),并且在表达式的替换部分中,捕获的文本可以使用\1第一次捕获的编号反向引用重新插入,\2对于第二个等等,例如

f='02-11-20 2:25 AM'
echo "$f" | sed 's/^\(..\)-\(..\)-\(..\).*$/\300-\1-\2/'

示例输出

两种方法产生相同的输出:

2000-02-11

如果您还有其他问题,请告诉我。


推荐阅读