正常化日期格式
01
normdata.sh
02
#!/bin/sh
03
04
# normdata.sh -- 在日期中将月份正常化为3个字母,第一个字母大写。
05
# 对于第7个脚本valid-date很有帮助的函数。
06
07
monthnoToName()
08
{
09
# 把变量'month'设置为一个适当的值
10
case $1 in
11
1 ) month="Jan";; 2 ) month="Feb";;
12
3 ) month="Mar";; 4 ) month="Apr";;
13
5 ) month="May";; 6 ) month="Jun";;
14
7 ) month="Jul";; 8 ) month="Aug";;
15
9 ) month="Sep";; 10) month="Oct";;
16
11) month="Nov";; 12) month="Dec";;
17
* )echo "$0: Unknown numeric month value $1" >&2; exit 1
18
esac
19
return 0
20
}
21
22
### 脚本的主要部分
23
24
if [ $# -ne 3 ]; then
25
echo "Usage: $0 month day year" >&2
26
echo "Typical input formats are August 3 1962 and 8 3 2002" >&2
27
exit 1
28
fi
29
30
if [ $3 -lt 99 ] || [ $3 -gt 9999 ]; then
31
echo "$0: expected four-digit year value." >&2; exit 1
32
fi
33
34
if [ -z $(echo $1 | sed 's/[[:digit:]]//g') ]; then
35
monthnoToName $1
36
else
37
# 正常化开头的3个字母,第一个大写,剩下的小写
38
month="$(echo $1 | cut -c1 | tr '[:lower:]' '[:upper:]')"
39
month="$month$(echo $1 | cut -c2-3 | tr '[:upper:]' '[:lower:]')"
40
fi
41
42
echo $month $2 $3
43
44
exit 0
脚本如何工作
注意第3个条件语句:
if [ -z $(echo $1 | sed 's/[[:digit:]]//g') ]; then
它去掉了所有的数字,然后使用-z来测试看看结果是不是为空。如果结果为空,第一个输入域肯定是一个或多个数字,所以调用函数monthnoToName后将它映射到了一个月份的名字上。如果不为空,通过2个子shell转义序列(即由$符号和左右圆括号括起来的序列,这样的目的是调用封装的命令,然后将输出替换掉),一个由cut和tr组成的管道就会用来生成月份。第一个序列仅仅是提取了第一个字符,然后用tr命令将它大写化。(注:序列echo $1 | cut -c1也
可以写成${1%${1#?}}。)第二个序列提取了第2和第3个字符,然后将它们小写化。
运行脚本:
为了确保对将来包含了normdata功能的脚本最大的适应性,这个脚本被设计成可以在命令行接受3个域的输入。如果你仅仅是想要交互式的使用这个脚本,相比之下,你要提示用户是3个域,不过这样的话,要是想从别的脚本调用normdate的话就不大方便了。
结果:
这个脚本完成了我们所期望的:只要日期格式相对简单点,就可以将它正常化,(已知的月份名字,月份的值在1-12之间,还有一个4个数字的年份)。比如:
结果
1 ./normdate.sh 8 3 62 2 ./normdate.sh: expected four-digit year value. 3 ./normdate.sh 8 3 1962 4 Aug 3 1962 5 ./normdate.sh AUGust 3 1962 6 Aug 3 1962
延伸阅读:
在你因为自己可以添加很多的扩展到这个脚本中而变得太兴奋之前,可以看看脚本7,它使用了normdate来正确话输入的日期。不管怎样,你现在就可以做的一个改动是,马上增加下面的一小段代码到脚本的开头测试部分,你的脚本就可以接受形式为MM/DD/YYYY或MM-DD-YYYY格式的日期了:
1 if [ $# -eq 1 ]; then 2 set -- $(echo $1 | sed 's/[///-]/ /g') 3 fi
测试下:
1 ./normdate.sh March-11-1911 2 Mar 11 1911 3 ./normdate.sh 8/3/1962 4 Aug 3 1962
最后的脚本是:
01
完整的normdate.sh
02
#!/bin/sh
03
04
monthToName()
05
{
06
case $1 in
07
1 ) month="Jan";; 2 ) month="Feb";;
08
3 ) month="Mar";; 4 ) month="Apr";;
09
5 ) month="May";; 6 ) month="Jun";;
10
7 ) month="Jul";; 8 ) month="Aug";;
11
9 ) month="Sep";; 10) month="Oct";;
12
11) month="Nov";; 12) month="Dec";;
13
* )echo "$0: Unknown numeric month value $1" >&2; exit 1
14
esac
15
return 0
16
}
17
18
if [ $# -eq 1 ]; then
19
set -- $(echo $1 | sed 's/[///-]/ /g')
20
fi
21
22
if [ $# -ne 3 ]; then
23
echo "Usage: $0 month day year" >&2
24
echo "Typical input formats are August 3 1962 and 8 3 2002" >&2
25
exit 1
26
fi
27
28
if [ $3 -lt 99 ] || [ $3 -gt 9999 ]; then
29
echo "$0: expected four-digit year value." >&2; exit 1
30
fi
31
32
if [ -z $(echo $1 | sed 's/[[:digit:]]//g') ]; then
33
monthToName $1
34
else
35
month="$(echo $1 | cut -c1 | tr '[:lower:]' '[:upper:]')"
36
month="$month$(echo $1 | cut -c2-3 | tr '[:upper:]' '[:lower:]')"
37
fi
38
39
echo $month $2 $3
40
41
exit 0