- 论坛徽章:
- 0
|
又翻译了一小段,看不懂我翻译的就去看英文原著![]()
6.怎么计算日期:
这主要取决于你大脑里的想法
a.怎么获取昨天的日期
GNU版本的date有很多好用的人性化的新特性,例如
获取昨天的日期:
$ date --date yesterday
获取明天的日期:
$ date --date tomorrow
GNU版本的date的man文档中,里面有更多的其他选项,可以得到过去的,或者将来的多余一天的日期.
FreeBSD版本的date同样也有很多扩展选项,可以像下面的方法使用.
$ date
Wed Oct 22 13:48:29 CDT 2003
$ date -v-1d
Tue Oct 21 13:45:16 CDT 2003
任意调整TZ变量(这是个时区变量)并不是一个可靠的办法.如果你的确没有GNU版本或者FreeBSD版本的date,确实需要这么做,那么请参考g章节“任意日期算法”
b.关于文件的日期(新旧)#Finding elapsed time
若你需要测试一个文件的日期是否比另外一个文件的日期早,你可以这么做(在 bash, pdksh, ksh93环境下)
$ [[ file1 -ot file2 ]] && echo file1 is older
或者你也可以使用find命令,查找一个目录下比目标文件旧或者早的文件:
$ find . -name '*.c' -newer test.c
c.获取已经用掉的时间 #Finding elapsed time
如果你想获取已经用掉的时间,也许是因为你想知道某些操作什么时候超时了,一些shell(bash,ksh,zsh)有一个 SECONDS变量,可以告诉你从shell的某个触发条件开始到现在(since the invocation of the shell)一共多少秒,或者从SECONDS变量最后一次被重置的时间到现在一共多少秒.
ksh93有一个取决于locale的浮动点seconds .
在zsh4.1或者以上的版本可以定义浮动点:float SECONDS
在zsh4.1或者以上的版本中同样有一个$EPOCHSECONDS变量,保存从1970-1-1 0:0:0 UTC到现在的秒数(see zsh/datetime module)
d.计算闰年
在公历中,闰年被定义为:可以被4除尽的年份大部分是闰年,能被100整除而不能被400整除的年份不是闰年,这听起来似乎比较麻烦,实际上,我不会有那么大的岁数 .
在很久以前,欧洲采用的大都为儒略历,只有被4整除的年份才是闰年.
为了方便和应该的日期相协调,标准的cal程序可以在儒略历和公历从1752年9月之间切换(see cal 9 1752).公历(由罗马教皇格里高利十三世于1582年颁布施行)从1582开始被很多国家使用.
Ksh可以完成的一些功能(after 1600 AD/CE#注:这里不知道怎么翻译)有:
isleap()
{
y=$1
four=$(( $y % 4 ))
hundred=$(( $y % 100 ))
fourhundred=$(( $y % 400 ))
if [ $four -eq 0 ];then
if [ $hundred -eq 0 ];then
if [ $fourhundred -eq 0 ];then
echo leap year
else
echo not a leap year
fi
else
echo leap year
fi
else
echo not a leap year
fi
}
Or, valid with any date with the same calendar switch day as POSIX cal's (POSIX syntax):
is_leap_year() # args: year
# NB: year before year 1 is year -1, not 0.
{
[ "$1" -lt 0 ] && set -- "$(($1 + 1))"
[ "$(($1 % 4))" -eq 0 ] && {
[ "$(($1 % 100))" -ne 0 ] || [ "$(($1 % 400))" -eq 0 ] \
|| [ "$1" -le 1752 ]
}
}
或者在一些 Bourne shell 中(see COPYING[1]):
is_leap_year() { ## USAGE: is_leap_year [year]
isl_year=${1:-`date +%Y`}
case $isl_year in
*0[48] |\
*[2468][048] |\
*[13579][26] |\
*[13579][26]0|\
*[2468][048]00 |\
*[13579][26]00 ) _IS_LEAP_YEAR=1
return 0 ;;
*) _IS_LEAP_YEAR=0
return 1 ;;
esac
}
在FreeBSD系统中,date使用-f选项来绕过当前年份(假定)中的2月29日,然后再次打印月中的所有天数来确认是否真的有这一天(注意,你同样需要使用-j参数,负责系统会认为你想要重新设置时间):
if [ $(date -jf%Y%m%d $(date +%Y0229) +%d) = 29 ]; then
echo Leap year!
fi
e.计算一个月中的最后一天.
这里有N种方法可以实现这个要求,下面是讨论组中的一个取样.
在任何的Bourne-type shell(调用了上面的is_leap_year() 函数,当月份是2的时候)(see COPYING[1]):
days_in_month() { ## USAGE: days_in_month [month [year]]
if [ -n "$1" ]
then
dim_m=$1
dim_y=$2
else
eval `date "+dim_m=%m dim_y=%Y"`
fi
case $dim_m in
9|09|4|04|6|06|11) _DAYS_IN_MONTH=30 ;;
1|01|3|03|5|05|7|07|8|08|10|12) _DAYS_IN_MONTH=31 ;;
2|02) is_leap_year ${dim_y:-`date +%Y`} &&
_DAYS_IN_MONTH=29 || _DAYS_IN_MONTH=28 ;;
esac
[ ${SILENT_FUNCS:-0} -eq 1 ] || echo $_DAYS_IN_MONTH
}
用GNU date
year=2003
month=9
date -d "$year/$month/1 +1 month -1 day" +%d
在FreeBSD系统中,使用date的-v-1d 选项可以取得下个月的前一天:
$ MONTH=12
$ date -v-1d -jf%Y-%m-%d $(date +%Y-$(((MONTH+1)%12))-01) +%d
31
在shell中使用cal(但是小心执行cal会一次输出多于一个月)
month=9 ; year=2003 # adjust
##
for lday in `cal $month $year` ; do : ; done
echo $lday
## or
set -- `cal $month $year` ; eval lday=\${$#}
echo $lday
In ksh, bash and zsh:
: $(cal)
days_in_month=$_
In zsh:
days_in_month=${$(cal)[-1]}
f.给出任意一个日期,计算星期几
Zeller's Rule是一个大家都熟悉的算法,在数据结构与算法中,我们可以找到它的详细解释.相关网页:
NIST:
http://www.nist.gov/dads/
Also, a fuller explanation is available at
http://www.merlyn.demon.co.uk/zeller-c.htm#ZC
An example in C, with a short explanation, is given at
http://wwwcdf.pd.infn.it/MLO/Calendars/Notes.html#zeller
#译者添加 Zeller's Rule: f = k + [(13*m-1)/5] + D + [D/4] + [C/4] - 2*C. #[]是取整的意思,例如[3.79]=3.k日、m月(三月为首1, 二月为后12)、D年的后2位(一月、二月时要减1)、C百年.
Ksh(ksh93)中:
dayofweek()
{
# Implementation of a homework assignment given at
# http://carbon.cudenver.edu/~traup/fa02/lec/hw3.html
#
# call with day: 1 - 31
# month: March = 1, Jan & Feb are months 11 and
# 12 of the previous year.
# year: The year of the century
# c: The previous century
#
# For example, for July 4, 1989,
# m = 5, d = 4, y = 89, and c = 19,
# while for January 25, 1989,
# m = 11, d = 25, y = 88, and c = 19.
#
# The output is the day of the week with Sunday = 0,
# Monday = 1, etc.
d=$1
m=$2
y=$3
c=$4
A=$(( ($m * 13 - 1) / 5 ))
B=$(( $y / 4 ))
C=$(( $c / 4 ))
D=$(( $A + $B + $C + $d + $y - ($c * 2) ))
echo $(( $D % 7 ))
}
在FreeBSD系统中,使用date的-f选项来跳过date中的有趣的天数,+%A 来打印星期几.
g.任意日期计算
任意日期计算是十分复杂的.一种方法就是调用外部程序.或者用另外一种内置语言编程实现.例如:perl有封装了UNIX时间相关的函数,可以提供更多的方便的功能调用,C语言也可以轻松的实现(see the examples section). 要记住一点,严格的来说,unix系统里面的时间是有一个范围限制的.从1970年1月1日0:00:00开始到2038年1月19日3:14:07.c程序和perl程序,在这个范围外可能正常工作,也可能不正常工作,这取决于你的程序.
利用shell自身计算任意日期也不是不可能的,SysAdmin杂志上的一篇文章描述了一种计算方法:
http://www.samag.com/documents/s=8284/sam0307b/0307b.htm
在这个地方给了另外一种算法
http://groups.google.com/groups? ... f%40ogion.it.jyu.fi
在FreeBSD中,date的-f和-v选项覆盖了大部分你想做的东西,但只能计算上面提及,在这个范围内的日期.范围外的日期将不能工作.
同样,zsh4.1以上的版本有zsh/datetime 模块,提供了变量$EPOCHSECONDS 和strftime函数.
h.获取从新纪元(1970年1月1日午夜)开始的总秒数
-GNU date 有s%选项可以返回新纪元时间 (epoch time)
-更好的方法,使用awk.
awk 'BEGIN {srand(); printf("%d\n", srand())}'
因为当没有参数输入的时候,srand()默认采用当前的新纪元时间(epoch time)为种子,它同样也返回它的上一个种子的值,所以第二个调用返回了新纪元时间(epoch time).
注意:旧版本的awk不支持,这需要支持POSIX标准的srand(),例如,在solaris中/usr/bin/awk不支持,但是nawk 或者 /usr/xpg4/bin/awk则支持.
取决于顺序,若已经被调用过一次了,或者其它情况,则本次调用可能不是第二次调用.
-另外一个方法,使用perl,若你的系统上安装的有的话.
perl -le 'print time'
-同样,zsh4.1或者以上的版本具有 zsh/datetime 提供$EPOCHSECONDS变量和strftime函数
7.为什么有人告诉我RTFM?
因为你没有 
RTFM 是一个网络行话,全称是 "Read The F-ing Manual".
当有人问一个过去经常被问的问题的时候,并且man文档中有很清晰的答案,回答者已经疲惫于看到有人再次问同样的问题.
http://catb.org/~esr/jargon/html/R/RTFM.html
所以, 在你问问题之前,请RTFM(阅读一下man文档或者说man一下),Also, if you're new to the group, search Google Groups
http://groups.google.com/advanced_group_search
问问题之前,不要直接把你的作业贴上去除非你尝试了很久没有成功完成,并问一些经过思考过的问题,当你认真的思考过一些问题之后,人们大都乐于和你一起讨论你的问题,而不是直接贴个问题问别人要答案
8.怎么创建一个锁文件.
#译者注: <操作系统>课程中应该讲过,原子操作就是可以再细分的操作,而非原子操作就是不能在细分的操作,课程学的早,不太记得了.
千万要谨慎
在一个非原子操作中,调度程序可以停止一个进程,并执行另外一个可能具有同样功能或操作的进程.第二个进程,拥有完整的时间片,可能会完成操作,当控制权回到第一个进程中的时候,可能导致混乱.
避免这个问题的窍门就是做一些原子操作.有两种方法可以实现.一个是创建一个目录代替文件,另一个是创建一个符号链接.两个操作都被POSIX/SUS定义为原子的,事实上,他们的优点是都需要进行相应的系统调用,并且都是原子操作.
当在NFS分区上创建任何锁文件的时候都要小心,#不太会翻译这两句 NFS pretty much eliminates anything like atomicity(NFS分区对原子操作有更多的排斥作用? .若你想要创建一个锁文件,确保是在你的本地分区上操作,例如/tmp.
Netscape/Mozilla 使用链接符号的方法创建锁文件(事实上它在用户的家目录创建了它,尽管用户的家目录可能挂在NFS分区上),当它启动的时候它就创建了一个以及其正在运行的IP地址为名字的文件,然后它在试图创建一个名为"lock"并之前那个文件的链接符号,若这个链接已经存在,则link命令会抱错,在脚本中类似下面:
touch /tmp/xxx
ln -s /tmp/xxx /tmp/lockfile 2>/dev/null
ret=$?
rm /tmp/xxx
if [ $ret -ne 0 ];then
echo lockfile already exists
exit 1
else
echo success
fi
若你安装了procmail程序,另一个命令lockfile 也会一起被安装的.
9.怎么将DOS文件转换为unix文件,反之亦然
UNIX文本文件以LF ("line-feed" (ASCII 10)字符结尾,而DOS使用两个字符CR LF ("carriage return", "line feed"; ASCII 13, 10).
把DOS文件转换为UNIX文件,删除行末尾的CR字符(control-M) 即可,把UNIX文件转换为DOS文件,则在行末尾添加CR字符.
两个删除CR字符的方法:
sed 's/^M$//' dos.txt > unix.txt
tr -d '\r' < dosfile > unixfile
添加方法:
sed 's/$/^M/' unix.txt > dos.txt
注意 "^M"在这里是个内部控制字符,(CR,ASCII 13),许多shell允许输入内部控制字符,但要先输入^V 字符 (control-V), 结果如下:
用 ^V^M # 输入"^M".
尽管如此,zsh,bash或者ksh93允许以下操作:
sed $'s/$/\r/'
这里有个特殊的地方需要考虑 OS下的文本文件有时候在文件结尾会包含一个特殊字符^Z (ASCII 26,or octal 32), UNIX文本文件下没有这个字符,文件末尾的字符在unix下是不可见的,同样可以用删除CR字符的方法删除它:
tr -d '\r\032' < dosfile > unixfile
注意: sed不能解释这个字符,但awk可以,一个简单的方法做相反的转换:
$ awk '{printf "%s\r\n" $0}END{printf "%c", 26}' unixfile > dosfile
假定我们使用的不是旧版本的awk,在Solaris下不要使用/bin/awk (使用 nawk or /usr/xpg4/bin/awk in Solaris).
最后,你的系统可能安装了一些名为dos2unix和unix2dos的命令,或者d2u dos2unix 从dos 非标准程序,或者GNU recode:recode /CRLF
10.怎么设置shell prompt而改编xterm的标题
#不知道怎么翻译这一句"Gives escape sequences for xterm,"例如,把目前窗口的名字改为"XXX" (in bash):
$ echo -en "\033]2;XXX\007"
或者,更恰当点的:
$ printf '%b' '\e]2;XXX\a'
参考"为什么echo输出的结果不是我想要的?" |
|
评分
-
查看全部评分
|