shell - 如何在 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 格式获取日期?
解决方案
使用参数扩展
POSIX shell 提供参数扩展来从字符串的左(前)或右(后)的开头删除substring
a 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
字符子字符串。您可以使用以下方法检索月、日和年:string
start
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
如果您还有其他问题,请告诉我。
推荐阅读
- laravel - 使用 PHPUnit 运行 Laravel 测试,排队的作业似乎总是在同步模式下运行。如何以标准模式调度它们?
- apache - htaccess - 删除 .php 扩展名并保留变量
- docker - 在 docker 中提供 DOCKER_HOST 变量后,找不到本地图像
- maven - 如何定义对第三方 jar 的特定包的依赖。我不想要 Jar 的所有包,只需要几个特定的包
- python - 我如何计算python每1.5秒的周期数?
- ruby-on-rails - 如何将内存中的 MongoDB 与 Rails、Mongoid 和 Rspec 一起使用?
- shell - Rust:使用子进程 shell 调用 rustc
- java - Weblogic 12c 部署中的休眠错误
- javascript - 本地分配变量时未执行代码
- python - 如何使用 for-loop 修改现有 DataFrame?