标准化日期格式
时间:2008-03-21 来源:剑心通明
对于shell脚本的开发者来说,数据的资料格式不一致是一个很大的问题,要让它们能够标准化也是一个相当 棘手的问题。日期的格式是众多问题中的一个,因为日期的表示方式有许多种,即使我们使用"月日年"的方式来表示,我们也可能有不同的输入方式:月份的部份 我们可以输入英文的月份缩写或大写的全名。
基于这个理由,我特別编写一个基本的日期格式程序,这个程序对于你以后的脚本编写会有相当大的帮助。
脚本源代码
#!/bin/sh
# normdate -- Normalizes month field in date specification
# to three letters, first letter capitalized. A helper
# function for Script #7, valid-date. Exits w/ zero if no error.
monthnoToName()
{
# Sets the variable 'month' to the appropriate value
case $1 in
1 ) month="Jan" ;; 2 ) month="Feb" ;;
3 ) month="Mar" ;; 4 ) month="Apr" ;;
5 ) month="May" ;; 6 ) month="Jun" ;;
7 ) month="Jul" ;; 8 ) month="Aug" ;;
9 ) month="Sep" ;; 10) month="Oct" ;;
11) month="Nov" ;; 12) month="Dec" ;;
* ) echo "$0: Unknown numeric month value $1" >&2; exit 1
esac
return 0
}
## 主程序
if [ $# -ne 3 ] ; then
echo "Usage: $0 month day year" >&2
echo "Typical input formats are August 3 1962 and 8 3 2002" >&2
exit 1
fi
if [ $3 -lt 99 ] ; then
echo "$0: expected four-digit year value." >&2; exit 1
fi
if [ -z $(echo $1|sed 's/[[:digit:]]//g') ]; then
monthnoToName $1
else
# Normalize to first three letters, first upper, rest lowercase
month="$(echo $1|cut -c1|tr '[:lower:]' '[:upper:]')"
month="$month$(echo $1|cut -c2-3 | tr '[:upper:]' '[:lower:]')"
fi
echo $month $2 $3
exit 0
工作原理
注意第三个判断式:
if [ -z $(echo $1|sed 's/[[:digit:]]//g') ]; then
它会将所有的数字刪除,并且利用 -z 来进行测试结果是不是空白字元,如果是空白字元,表示第一个字必定是数字,那么程序会调用monthnoToName来做查表的动作。接下来的两行会利用 cut与tr将月份的字母进行分离及转换。第一行是分离出第一个字元,再利用tr命令将它转换成大写字母(之前提过,以POSIX而言 echo $1|cut -c1 这种写法也可以写成 ${1%${1#?}} )。第二行是将第二及第三个字母转换成小写字母:
month="$(echo $1|cut -c1|tr '[:lower:]' '[:upper:]')"
month="$month$(echo $1|cut -c2-3 | tr '[:upper:]' '[:lower:]')"
运行脚本
为了让该脚本normdate在以后能有更大的应用空间,我们把脚本设计成可以在命令列上输入三个栏位的程序。另外,如果你想让此程序更具互动性,你应该要提示使用者输入三个栏位。相比较之下,两者之间似乎是后者较难。
结果
对于这个程序,我们希望它能夠将一个简单的日期(已知的月份名称或月份数字及四位数的年份)变成一个标准的日期格式。举例:
$ normdate 8 3 62
normdate: expected four-digit year value.
$ normdate 8 3 1962
Aug 3 1962
$ normdate AUGUST 3 1962
Aug 3 1962
改进与加强
这个脚本有很大的扩充性。另一方面,只要做一点点的修改,我们就可以让这个脚本接受不同的日期格式,例如MM/DD/YYYY或者是MM-DD-YYYY,请将底下的程序代码附加在刚才我们提及的判断式前:
if [ $# -eq 1 ] ; then # try to compensate for / or - formats
set -- $(echo $1 | sed 's/[\/\-]/ /g')
fi
修改后,我们也可以输入这样的时间格式:
$ normdate March-11-1911
Mar 11 1911
$ normdate 8/3/1962
Aug 3 1962