- 论坛徽章:
- 0
|
很早以前翻译了一部分,后来一直没时间继续,以后三个月内也不会继续,有兴趣的可以继续翻译,本人语言功底有限,错误地方还请指正
Comp.unix.shell FAQ
来自: j.p.h@comcast.net (Joe Halpin)
新闻组:comp.unix.shell
题目:comp.unix.shell FAQ-常见问题解答
摘要:这份文档记录了一些在comp.unix.shell中经常被问到的问题的答案,你若想在讨论组内提问,你最好先阅读一下这份文档,看能否找到你要的答案。
Followup-To: comp.unix.shell
文档名字:unix-faq/shell/sh
提问频率:每月
版本: $Id: cus-faq.html,v 1.11 2005/09/01 17:39:36 jhalpin Exp $
维护人员:Joe Halpin
这份FAQ给出了一些在comp.unix.shell常常被提到的问题的答案,之所以用小写的unix是为了避免关于是否是Linux或者BSD的讨论,我们都认为是unix,这个不是这份文档的重点,我们忽略这个问题。
This document as a whole is Copyright (c) 2003 Joe Halpin. It may be copied freely. Exceptions are noted in individual answers.
Suggestions, complaints, et al, should be sent to the maintainer at j.p.h@comcast.net or posted to comp.unix.shell
关于shell的讨论有两个级别。
一个级别是shell作为OS的和用户之间的接口的自身使用的问题。例如:“我怎么在后台运行一个程序而继续做其他的事情?”或者“当我登陆的时候,我怎么设置自己的环境变量?”
另外一个级别是怎么去写shell脚本。包含使用标准unix程序编写shell脚本去完成一部分常见的工作,这将需要一些关于shell脚本编写的知识。然而,只要问题不是超出标准unix应用范畴的,应该都可以在这份FAQ中找到。
标准的unix应用程序被定义为:POSIX 或者 Single Unix Specification中的一种规格,他们现在被合称为"POSIX/SUS".详细描述可以在下面的网址中找到
http://www.opengroup.org/onlinepubs/007904975/toc.htm
可以在网上找到所有应用程序的man文档(包含shell自己的)。但是,你仍需要在你的系统上核对一下你将要使用的应用程序或者shell的man文档。目前,在标准和具体应用之间并没有进行完美的交流(事实上,我不清楚他们之间的任何协调和交流)。
这里还有另外一个FAQ,描述了标准化的成果的更多细节。
http://www.opengroup.org/austin/faq.html
这里还有一些其他不错的网站提供了shell和shell编程(包含UNIX应用程序)的信息。
包含:
http://www.shelldorado.com/
http://cfaj.freeshell.org/shell/
http://www.faqs.org/faqs/by-newsgroup/comp/comp.unix.shell.html
有可能用到的FAQ:
http://home.comcast.net/~j.p.h/
http://www.newsville.com/cgi-bin ... tly_Asked_Questions
---------------
免责声明
---------------
这份FAQ中给出的答案提供了最好的意指导,但是,它并不一定能被正确的应用于特殊的系统或者shell。对某些系统或者shell可能是完全错误的。你若不测试结果的话,它将会是你的程序的一个bug。
这份文档没有声明,也不保证所有答案的正确性。事实上,很多甚至没有经过测试。答案来源于一个或者多个新闻组中的正是成员,我相信他们是有能力的(当然,比我更有能力)但仍不保证答案的正确性。
难道我真的需要全部大写?希望不,但是周围有很多无聊的律师,所以,我想清楚的表达一下,在这份文档的精确性上:THERE ARE NO GUARANTEES。希望这份文档对学习shell编程的人有用,但它并不是一份supported product。你必须自己考虑这里的答案对你的所将要的工作是否有。
……
以下省去了,没有翻译,自己看算了 ^_^
Under no circumstances will the maintainer of this FAQ list, or any contributors to it, be held liable for any mistakes in this
document. If the answers work for you, well and good. If not, please tell me and I'll modify them appropriately so that this will be more useful.
If you don't agree to that, don't read any farther than this. Reading beyond this point indicates your agreement.
If you do test the answers and find a problem, please send email to the maintainer (see above), so it can be corrected, or (preferably) post a question to the newsgroup so it can be discussed and corrected if there's a problem.
A number of people have contributed to this FAQ, knowingly or unknowingly. Some of the answers were taken from previous postings in the group, and other people contributed questions and answers directly to the maintainer, which you are welcome to do as well.
Among the contributors is Heiner Steven, who also provided the momentum to get this FAQ list started. He maintains a web site about shell programming that has a lot of good stuff in it.
http://www.shelldorado.com/
目录:
0 拷贝
0a 术语表
Google
POSIX/SUS ("the standard")
UUOC
dotfile
portable
race condition
shebang
shells
top-posting
0b 使用echo的注意事项
1 怎么发送带附件的email
2 怎么在shell脚本中产生随机数
3 怎么使用带错误校验的ftp自动传输文件
4 怎么删除文件名中的空格字符
5 怎么使用telnet自动登录
6 计算日期的算法
7 为什么有人告诉我 RTFM
8 怎么创建一个锁文件
9 怎么将DOS文件转换为unix文件,反之亦然
10 怎么设置shell prompt而改编xterm的标题
11 在命令 cmd1|cmd2 中,我怎么得到cmd1的退出装体.
12 为什么会提示 “script.sh:not found”
13 为什么echo不能输出我想得到的东西.
14 文件名中带有空格,我怎么在循环中使用它们.
15 怎么改变默认的登录shell
16 什么时候我应该使用shell代替perl/python/ruby/tcl...
17 为什么不要使用c shell
18 怎么颠倒(翻转)一个文件
19 怎么删除最后几行
20 怎么得到文件的大小和修改日期.
21 给定一个进程名,我怎么得到进程ID?或者给定一个进程ID,我怎么确认这个进程仍然在运行?
22 怎么使用脚本改变当前的环境变量?
23 怎么把*.foo重命名为*.bar?
24 在awk脚本中怎么调用shell量?
25 怎么获得一个有时间限制的用户输入?
26 怎么从用户的输入中得到一个字符?
27 为什么我的.profile文件没有被读到?
28 为什么提示: "[5" not found in "[$1 -eq 2]"?
29 怎么正确显示变量 $var(带有回车符)的内容?
30 怎么把一个路径名分割为目录名和文件名?
31 带参数的alias
32 怎么处理以特殊字符开始的文件名?
33 为什么得不到循环中全局变量的值?
34 怎么使用ftp批量下载和上传?
附录A 一些实例脚本
附录B 参考书目.相应的用方括号括起来的数字将会出现在文章中,例如[1]
译者注:版权说明,翻译省去,自己注意
ANSWERS
0 COPYING
Some contributors may copyright their submissions and license them
differently than this document.
[1] Chris F.A. Johnson. Examples marked with COPYING[1] were
contributed by Chris F.A. Johnson. He has copyrighted these
examples, and licensed them under the GNU General Public
License (GPL). Copying them directly into another script will
cause that script to also come under the GPL. For details see
http://www.fsf.org/licenses/licenses.html
0a 术语表
Google
它是互联网上的一种搜索工具,它能搜索到数年前的信息,现在作为一个标准的参考指导人们去搜索已经讨论过的话题,这对搜索shell编程(以及其他任何东西)的相关问题来说,是一个非常好的起点。
http://groups.google.com/advanced_group_search
-------------------------------
POSIX/SUS ("the standard")
POSIX (Portable Operating System Interface)和SUS (Single Unix
Specification)已经结合成为一个标准。这就是平时人们讨论unix的时候经常涉及到的“标准”。当在讨论组中涉及到POSIX shell的时候,他们讨论的就是这个标准,你可以在以下网址中找到此标准的详细描述
http://www.opengroup.org/onlinepubs/007904975/toc.htm
-------------------------------
UUOC
这个缩写的全拼是"Useless use of cat"(没有使用cat的必要).它经常指本来可以使用重定向来代替cat的shell脚本。使用重定向要比使用cat更加有效率,因为cat是调用外部程序从而产生了一个新的进程。例如:
$ cat file | tr -d 'xyz'
这个命令产生了两个进程,一个是cat,一个是tr。下面的语句将更有效率
$ tr -d 'xyz' < file
一般情况下,"cat file | somecommand"可以被更有效率的命令代替为"somecommand < file"或者多文件输入
$ somecommand file [file ...]
但是,最好阅读一下有关命令“somecommand”的man文档,以确定该命令是否支持该语法。
dotfile 点文件
这是指文件名以“.”开头的文件,你若不使用ls命令到的-a选项(ls的新版本可能是-A选项,检查一下你的man 文档)的话,将不会显示出来。一般情况下,它们都是配置文件,被应用程序来存储配置文件的子目录,NFS swap 文件等等。
Portable
The word "portable" means different things to different people, in different situations, which is to say, there isn't one definition of "portable".
“portable”是指在不同的事物,不同的人会有不同的办法。或者是说,对于“portable”不只一种定义方法。
一个极端,a portable script 可以在任何shell,任何操作系统上完美的运行。但是,这种完美的脚本并不存在(因为有些操作系统甚至可能没有shell)。如果我们把操作系统的范围限定到unix(我们一开始就应该知道这是comp.unix.shell),唯一真正的portable scripts是那些不调用shell的内置命令和语法,完全调用外部命令,例如:
echo Hello World
也许合格,然而,但是并不是任何一个命令都可以做到更好。
相对与标准,几乎没有probably的脚本存在,“portable”更多的时候是指脚本能在不同的shell,不同的系统环境下的,脚本的可移植运行的程度。
例如,如果你要为一个应用程序写一个安装脚本,程序的运行平台是已经被指定了的,这时问题已经被完美的限定在一定范围内。Shell可以选择在限定的系统上都已经安装存在的shell,语法的使用选择在不同的目标平台上的shell的语法的最小公共子集。
脚本的portable程度取决于你,或者你对指定的shell脚本的需求。
-------------------------------
race condition(资源竞争)
这是指两个实体(进程,线程等)试图存取一个共享资源,或者完成同一件事。它的结果取决于两个实体的执行顺序。
-------------------------------
shebang (沙邦,或者翻译为shell头吧 ――!)
这是指shell脚本的第一行,它告诉操作系统应该调用哪个解释器(shell)
#!/path/to/shell [ argument ]
/path/to/shell可能是/bin/sh, /usr/local/bin/bash等
这一行仅被操作系统解释,如果一个脚本(test.sh)在命令行下被作为一个参数来执行,例如:
$ sh test.sh
这时sh将解释test.sh,对于sh来说shebang只是一个注释,执行的时候将忽略它。
shells
讨论组中讨论的很多shell类型中包含:
sh
csh
pdksh
ksh88
ksh93
tcsh
zsh
rc
es
bash
ash
dash
这些(有更多)shell的名字在讨论组中将被做为参考。一些shell的比较可以在下面的地址中看到。
http://www.faqs.org/faqs/unix-faq/shell/shell-differences/
但是,它并没有比较ksh88, ksh93 和 pdksh的差别,它们并不是完全兼容的。
―――――――――――――――――――
top-posting
A. top posting
Q. What's the most irritating way to respond on usenet?
Please see the following:
http://catb.org/~esr/jargon/html/T/top-post.html
http://www.uwasa.fi/~ts/http/quote.html
http://members.fortunecity.com/nnqweb/
http://www.guckes.net/mail/editing.html
0b 使用echo的注意事项。
这不是一个真正的FAQ,但是经常会遇到有关echo的讨论,所以它出现在这份FAQ中是有原因的。
在不同的环境下,echo命令对它的参数的解释并不是一致的。被引号引起来的带反斜线的字符串有时候被解释为一种意思,有时候又被解释为另外一种意思。
同样,若被echo输出的字符串并不在脚本中,那么它可能含有shell的meta字符,它同样可以产生影响。事实上,传给echo的外部输入字符串应该被引号引起来。
例如:
s="a string with\na newline and\ta tab"
下面是不同shell的输出结果:
------
bash:
$ echo "$s"
a string with\na newline and\ta tab
$ echo -e "$s"
a string with
a newline and a tab
-------
pdksh:
$ echo "$s"
a string with
a newline and a tab
$ echo -e "$s"
$ echo "$s"
a string with
a newline and a tab
--------
ksh88:
$ echo "$s"
a string with
a newline and a tab
$ echo -e "$s"
-e a string with
a newline and a tab
-------
ksh93:
$ echo "$s"
a string with\na newline and\ta tab
$ echo -e "$s"
-e a string with\na newline and\ta tab
注意,ksh93认为参数处理有一下两种情况决定,包含’\’或者第一个传入参数以-开头。
http://www.cs.princeton.edu/~jlk/kornshell/doc/man93.html
POSIX 不允许-e选项。它也对-n选项和带’\’的执行结果给了定义。然而,在XSI-conforming系统上,它不接受选项,定义了使用反斜线引用的字符。
通常,echo的行为是系统或者shell(或者系统与shell的共同结果)取决于它的参数是否包含反斜线,或者第一个参数是否为-n或者-e
使用echo的最大问题是使用它输出脚本直接获取的输入(或者用户输入,或者从文件中读取)。这些字符串可能包含’\’字符,若是这样的话,结果并不是你想要的。
Print在许多shell中是一个可以用到的命令,或许printf会更加的portable。另外,here文档将会给出我们一个可以预知的输出结果,它并不展开逃脱字符(反斜线)
cat <<EOF
$s
EOF
产生
a string with\na newline and\ta tab
所以最好不要使用echo,除非你可以确定它将在你的shell中产生什么样的结果。
1, 怎么发送一个带附件的邮件。
a) 使用uuencode
这是一个最简单的方法例如
$ uuencode surfing.jpeg surfing.jpeg | mail someone@some.where
可以很好的发送文档。
$ (cat mailtext; uuencode surfing.jpeg surfing.jpeg) |
mail someone@some.where
b) 使用MIME
$ metasend -b -t someone@some.where -s "Hear our son!" \
-m audio/basic -f crying.au
从下面的连接中你可以得到更多的合适的例子
Http://www.shelldorado.com/articles/mailattachments.html
c) Use pine (with a patch) or mutt # or mutt不知道怎么翻译。
2, 怎么在shell脚本中产生随机数?
这个取决于shell和OS可用的工具。
a.一些shell有一个变量为 RANDOM,每次调用它的时候将产生一个不同的值,若你的shell有这个变量:
$ number=$RANDOM 将会产生随机数字。
b.有些系统有一个/dev/urandom设备,它产生一个bits流。可以被dd(1)存取。一个例子(from a more extensive discussion of different techniques at http://www.shelldorado.com/scripts/cmds/rand)
n=`dd if=/dev/urandom bs=1 count=4 2>/dev/null | od -t u4 | \
awk 'NR==1 {print $2}'`
同样
od -vAn -N4 -tu4 < /dev/urandom
c.使用外部程序,如awk(1),它可以产生随机数,,在不同的shell和不同的操作系统之间,这是一个非常portable的方法。
awk 'BEGIN {srand();print rand()}'
注意,旧版本awk并不支持这种用法,这需要支持POSIX srand()的版本。例如,在solaris上,/usr/bin/awk不工作,但是/usr/xpg4/bin/awk却能达到效果。
同样,你在同一时间内调用此命令的次数多于一次,你将得到和上一次同样的结果。
3.怎么使用带错误校验的ftp自动传输文件
首先,这里有工具可以做到:curl, wget, lftp, ncftp。但是,通常情况下系统并不自带这些程序,你需要安装它们。
zsh (version 4 and above)提供了一个ftp工具。
查看 "info –f zsh -n 'zsh/zftp Module'"
#! /usr/bin/zsh
zftp open host user passwd || exit
zftp get /remote/file > /local/file; r=$?
zftp close && exit r
使用系统的ftp命令,两种方法。
1 使用-n选项。不用-n选项的话,系统将等待用户输入password,所以你将不得不使用“expect”,使用-n,你像使用其他ftp命令一样提供用户名和密码。
#! /bin/sh
ftp -n << EOF
open ftp.domain.org
user anonymous ${LOGNAME:-`who am i`}@
binary
get /remote/file /local/file
bye
EOF
错误检测将不存在(若open失败,后面的发送语句将同样执行)
2 使用~/.netrc
若你使用
<<
machine ftp.domain.org
login mylogin
password mypasswd
macdef init
binary
get /remote/file /local/file
bye
>>
(最后几行空行)在你的~/.netrc(确保它不是所有人可读的),执行"ftp ftp.domain.org",ftp将会找到匹配的“机器”在你的~/.netrc中,使用可用的参数进行ftp传输。
至少在Linux, FreeBSD, Solaris, HPUX上可以工作。
4 怎么删除文件名中的空格字符
Unix下的文件名可以包含所有的不可视字符,不只是空格.但下面的只举例一些只对空格有用的例子.
a.利用awk,sed等工具中的替换功能.
f=`printf '%s\n' "$filename" | sed 's/ /_/g'`
f=`printf '%s\n' "$filename" | awk '{gsub(" ","_");print $0}'`
f=`printf '%s\n' "$filename" | tr ' ' _`
在tr命令行中添加必要的字符(请参阅tr的man文档,找出逃脱符的顺序)
另外(准确的说,并不一定是一行),例如:
f=`tr ' ' _ <<EOF
$filename
EOF
参考章节0a “使用echo的注意事项” 了解为什么不在这里使用echo
b.使用shell的substitution功能(若你的shell有此功能的话),检查你的shell的man文档(极有可能在像这样的章节"Parameter expansion"下面).例如:
f=${filename// /_}
使用zsh
autoload -U zmv
zmv '* *' '$f:gs/ /_/'
应该注意zmv的置换功能重命名了文件,而其他的置换功能仅仅是更新了变量.
=============================================
5 怎么使用telnet自动登录
这个已经超出了shell编程的范畴,最好使用专门的编程语言像expect之类的来完成它,参考http://expect.nist.gov/
使用perl的CPAN的telnet模块一样完成
=============================================
6 计算日期的算法
7 为什么有人告诉我 RTFM
8 怎么创建一个锁文件
9 怎么将DOS文件转换为unix文件,反之亦然
10 怎么设置shell prompt而改编xterm的标题
11 在命令 cmd1|cmd2 中,我怎么得到cmd1的退出装体.
12 为什么会提示 “script.sh:not found”
13 为什么echo不能输出我想得到的东西.
14 文件名中带有空格,我怎么在循环中使用它们.
15 怎么改变默认的登录shell
16 什么时候我应该使用shell代替perl/python/ruby/tcl...
17 为什么不要使用c shell
18 怎么颠倒(翻转)一个文件
[ 本帖最后由 大蚂蚁 于 2007-1-27 06:17 编辑 ] |
评分
-
查看全部评分
|