免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2839 | 回复: 3
打印 上一主题 下一主题

谁能推荐一下cshell书籍 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-05-07 22:10 |只看该作者 |倒序浏览
今天去北京海淀图书城看了好长时间也没有找到一本好书。我们公司不能上网,所以手头上必须有一本比较全面而且相当有深度的书作为参考资料。我对shell处于已经入门的阶段,可以写一些简单工具了,但是做一些复杂的东西还是不行,譬如说:文件比较之类的。各位能人能否推荐一本好书,呵呵,一本就可以。

论坛徽章:
0
2 [报告]
发表于 2006-05-07 22:15 |只看该作者
我的qq:498020486.可以直接找我!
<<LINUX与UNIX Shell编程指南>>是一本不错的书,还有没有讲解shell更为深入全面一点的。多谢了。

[ 本帖最后由 hgdzhang 于 2006-5-7 22:24 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2006-05-08 16:57 |只看该作者

Csh Programming Considered Harmful



  1. From: tchrist@cs.Colorado.EDU (Tom Christiansen)
  2. Date: 1 Oct 93 19:26:41 GMT
  3. Newsgroups: comp.unix.shell,comp.unix.questions,comp.unix.programmer,news.answers
  4. Subject: Csh Programming Considered Harmful

  5. Archive-name: unix-faq/shell/csh-whynot
  6. Version: $Id: csh-faq,v 1.5 93/10/01 13:26:05 tchrist Exp Locker: tchrist $

  7. The following periodic article answers in excruciating detail
  8. the frequently asked question "Why shouldn't I program in csh?".
  9. It is available for anon FTP from convex.com in /pub/csh.whynot .


  10.                *** CSH PROGRAMMING CONSIDERED HARMFUL ***

  11.     Resolved: The csh is a tool utterly inadequate for programming,
  12.               and its use for such purposes should be strictly banned!

  13. I am continually shocked and dismayed to see people write test cases,
  14. install scripts, and other random hackery using the csh.  Lack of
  15. proficiency in the Bourne shell has been known to cause errors in /etc/rc
  16. and .cronrc files, which is a problem, because you *must* write these files
  17. in that language.

  18. The csh is seductive because the conditionals are more C-like, so the path
  19. of least resistance is chosen and a csh script is written.  Sadly, this is
  20. a lost cause, and the programmer seldom even realizes it, even when they
  21. find that many simple things they wish to do range from cumbersome to
  22. impossible in the csh.


  23. 1. FILE DESCRIPTORS

  24. The most common problem encountered in csh programming is that
  25. you can't do file-descriptor manipulation.  All you are able to
  26. do is redirect stdin, or stdout, or dup stderr into stdout.
  27. Bourne-compatible shells offer you an abundance of more exotic
  28. possibilities.   

  29. 1a. Writing Files

  30. In the Bourne shell, you can open or dup arbitrary file descriptors.
  31. For example,

  32.     exec 2>errs.out

  33. means that from then on, stderr goes into errs file.

  34. Or what if you just want to throw away stderr and leave stdout
  35. alone?    Pretty simple operation, eh?

  36.     cmd 2>/dev/null

  37. Works in the Bourne shell.  In the csh, you can only make a pitiful
  38. attempt like this:

  39.     (cmd > /dev/tty) >& /dev/null

  40. But who said that stdout was my tty?  So it's wrong.  This simple
  41. operation *CANNOT BE DONE* in the csh.


  42. Along these same lines, you can't direct error messages in csh scripts
  43. out stderr as is considered proper.  In the Bourne shell, you might say:

  44.         echo "$0: cannot find $file" 1>&2

  45. but in the csh, you can't redirect stdout out stderr, so you end
  46. up doing something silly like this:

  47.         sh -c 'echo "$0: cannot find $file" 1>&2'

  48. 1b. Reading Files

  49. In the csh, all you've got is $<, which reads a line from your tty.  What
  50. if you've redirected stdin?  Tough noogies, you still get your tty, which
  51. you really can't redirect.  Now, the read statement
  52. in the Bourne shell allows you to read from stdin, which catches
  53. redirection.  It also means that you can do things like this:

  54.     exec 3<file1
  55.     exec 4<file2

  56. Now you can read from fd 3 and get lines from file1, or from file2 through
  57. fd 4.   In modern, Bourne-like shells, this suffices:

  58.     read some_var 0<&3
  59.     read another_var 0<&4

  60. Although in older ones where read only goes from 0, you trick it:

  61.     exec 5<&0  # save old stdin
  62.     exec 0<&3; read some_var
  63.     exec 0<&4; read another_var
  64.     exec 0<&5  # restore it


  65. 1c. Closing FDs

  66. In the Bourne shell, you can close file descriptors you don't
  67. want open, like 2>&-, which isn't the same as redirecting it
  68. to /dev/null.

  69. 1d. More Elaborate Combinations

  70. Maybe you want to pipe stderr to a command and leave stdout alone.
  71. Not too hard an idea, right?  You can't do this in the csh as I
  72. mentioned in 1a.  In a Bourne shell, you can do things like this:

  73.     exec 3>&1; grep yyy xxx 2>&1 1>&3 3>&- | sed s/file/foobar/ 1>&2 3>&-
  74.     grep: xxx: No such foobar or directory

  75. Normal output would be unaffected.  The closes there were in case
  76. something really cared about all its FDs.  We send stderr to sed,
  77. and then put it back out 2.

  78. Consider the pipeline:

  79.     A | B | C

  80. You want to know the status of C, well, that's easy: it's in $?, or
  81. $status in csh.  But if you want it from A, you're out of luck -- if
  82. you're in the csh, that is.  In the Bourne shell, you can get it, although
  83. doing so is a bit tricky.  Here's something I had to do where I ran dd's
  84. stderr into a grep -v pipe to get rid of the records in/out noise, but had
  85. to return the dd's exit status, not the grep's:

  86.     device=/dev/rmt8
  87.     dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
  88.     exec 3>&1
  89.     status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
  90.                 egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
  91.     exit $status;


  92. The csh has also been known to close all open file descriptors besides
  93. the ones it knows about, making it unsuitable for applications that
  94. intend to inherit open file descriptors.


  95. 2. COMMAND ORTHOGONALITY

  96. 2a. Built-ins

  97. The csh is a horrid botch with its built-ins.  You can't put them
  98. together in many reasonable ways.   Even simple little things like this:       

  99.             % time | echo

  100. which while nonsensical, shouldn't give me this message:

  101.             Reset tty pgrp from 9341 to 26678

  102. Others are more fun:

  103.             % sleep 1 | while
  104.             while: Too few arguments.
  105.             [5] 9402
  106.             % jobs
  107.             [5]     9402 Done                 sleep |


  108. Some can even hang your shell.  Try typing ^Z while you're sourcing
  109. something, or redirecting a source command.  Just make sure you have
  110. another window handy.  Or try

  111.     % history | more

  112. on some systems.

  113. Aliases are not evaluated everywhere you would like them do be:

  114.     % alias lu 'ls -u'
  115.     % lu
  116.     HISTORY  News     bin      fortran  lib      lyrics   misc     tex
  117.     Mail     TEX      dehnung  hpview   logs     mbox     netlib
  118.     % repeat 3 lu
  119.     lu: Command not found.
  120.     lu: Command not found.
  121.     lu: Command not found.

  122.     % time lu
  123.     lu: Command not found.


  124. 2b. Flow control

  125. You can't mix flow-control and commands, like this:
  126.    
  127.     who | while read line; do
  128.         echo "gotta $line"
  129.     done


  130. You can't combine multiline constructs in a csh using semicolons.
  131. There's no easy way to do this

  132.     alias cmd 'if (foo) then bar; else snark; endif'


  133. You can't perform redirections with if statements that are
  134. evaluated solely for their exit status:

  135.     if ( { grep vt100 /etc/termcap > /dev/null } ) echo ok

  136. And even pipes don't work:

  137.     if ( { grep vt100 /etc/termcap | sed 's/$/###' } ) echo ok

  138. But these work just fine in the Bourne shell:

  139.     if grep vt100 /etc/termcap > /dev/null ; then echo ok; fi   

  140.     if grep vt100 /etc/termcap | sed 's/$/###/' ; then echo ok; fi


  141. Consider the following reasonable construct:

  142.   if ( { command1 | command2 } ) then
  143.       ...
  144.   endif

  145. The output of command1 won't go into the input of command2.  You will get
  146. the output of both commands on standard output.  No error is raised.  In
  147. the Bourne shell or its clones, you would say

  148.     if command1 | command2 ; then
  149.         ...
  150.     fi


  151. 2c. Stupid parsing bugs

  152. Certain reasonable things just don't work, like this:

  153.     % kill -1 `cat foo`
  154.     `cat foo`: Ambiguous.

  155. But this is ok:

  156.     % /bin/kill -1 `cat foo`

  157. If you have a stopped job:

  158.     [2]     Stopped              rlogin globhost

  159. You should be able to kill it with

  160.     % kill %?glob
  161.     kill: No match

  162. but

  163.     % fg %?glob

  164. works.

  165. White space can matter:

  166.     if(expr)

  167. may fail on some versions of csh, while

  168.     if (expr)

  169. works!



  170. 3. SIGNALS

  171. In the csh, all you can do with signals is trap SIGINT.  In the Bourne
  172. shell, you can trap any signal, or the end-of-program exit.    For example,
  173. to blow away a tempfile on any of a variety of signals:

  174.     $ trap 'rm -f /usr/adm/tmp/i$$ ;
  175.             echo "ERROR: abnormal exit";
  176.             exit' 1 2 3 15

  177.     $ trap 'rm tmp.$$' 0   # on program exit



  178. 4. QUOTING

  179. You can't quote things reasonably in the csh:

  180.     set foo = "Bill asked, \"How's tricks?\""

  181. doesn't work.  This makes it really hard to construct strings with
  182. mixed quotes in them.  In the Bourne shell, this works just fine.
  183. In fact, so does this:

  184.      cd /mnt; /usr/ucb/finger -m -s `ls \`u\``

  185. Dollar signs cannot be escaped in double quotes in the csh.  Ug.

  186.     set foo = "this is a \$dollar quoted and this is $HOME not quoted"
  187.     dollar: Undefined variable.

  188. You have to use backslashes for newlines, and it's just darn hard to
  189. get them into strings sometimes.

  190.     set foo = "this \
  191.     and that";
  192.     echo $foo
  193.     this  and that
  194.     echo "$foo"
  195.     Unmatched ".  

  196. Say what?  You don't have these problems in the Bourne shell, where it's
  197. just fine to write things like this:

  198.     echo         'This is
  199.              some text that contains
  200.              several newlines.'


  201. As distributed, quoting history references is a challenge.  Consider:

  202.     % mail adec23!alberta!pixel.Convex.COM!tchrist
  203.     alberta!pixel.Convex.COM!tchri: Event not found.


  204. 5. VARIABLE SYNTAX

  205. There's this big difference between global (environment) and local
  206. (shell) variables.  In csh, you use a totally different syntax
  207. to set one from the other.  

  208. In the Bourne shell, this
  209.     VAR=foo cmds args
  210. is the same as
  211.     (export VAR; VAR=foo; cmd args)
  212. or csh's
  213.     (setenv VAR;  cmd args)

  214. You can't use :t, :h, etc on envariables.  Watch:
  215.         echo Try testing with $SHELL:t

  216. It's really nice to be able to say
  217.    
  218.     ${PAGER-more}
  219. or
  220.     FOO=${BAR:-${BAZ}}

  221. to be able to run the user's PAGER if set, and more otherwise.
  222. You can't do this in the csh.  It takes more verbiage.

  223. You can't get the process number of the last background command from the
  224. csh, something you might like to do if you're starting up several jobs in
  225. the background.  In the Bourne shell, the pid of the last command put in
  226. the background is available in $!.

  227. The csh is also flaky about what it does when it imports an
  228. environment variable into a local shell variable, as it does
  229. with HOME, USER, PATH, and TERM.  Consider this:

  230.     % setenv TERM '`/bin/ls -l / > /dev/tty`'
  231.     % csh -f

  232. And watch the fun!


  233. 6. EXPRESSION EVALUATION

  234. Consider this statement in the csh:


  235.     if ($?MANPAGER) setenv PAGER $MANPAGER


  236. Despite your attempts to only set PAGER when you want
  237. to, the csh aborts:

  238.     MANPAGER: Undefined variable.

  239. That's because it parses the whole line anyway AND EVALUATES IT!
  240. You have to write this:

  241.     if ($?MANPAGER) then
  242.         setenv PAGER $MANPAGER
  243.     endif

  244. That's the same problem you have here:

  245.     if ($?X && $X == 'foo') echo ok
  246.     X: Undefined variable

  247. This forces you to write a couple nested if statements.  This is highly
  248. undesirable because it renders short-circuit booleans useless in
  249. situations like these.  If the csh were the really C-like, you would
  250. expect to be able to safely employ this kind of logic.  Consider the
  251. common C construct:

  252.     if (p && p->member)

  253. Undefined variables are not fatal errors in the Bourne shell, so
  254. this issue does not arise there.

  255. While the csh does have built-in expression handling, it's not
  256. what you might think.  In fact, it's space sensitive.  This is an
  257. error

  258.    @ a = 4/2

  259. but this is ok

  260.    @ a = 4 / 2


  261. The ad hoc parsing csh employs fouls you up in other places
  262. as well.  Consider:

  263.     % alias foo 'echo hi' ; foo
  264.     foo: Command not found.
  265.     % foo
  266.     hi



  267. 7. ERROR HANDLING

  268. Wouldn't it be nice to know you had an error in your script before
  269. you ran it?   That's what the -n flag is for: just check the syntax.
  270. This is especially good to make sure seldom taken segments of code
  271. code are correct.  Alas, the csh implementation of this doesn't work.
  272. Consider this statement:

  273.     exit (i)

  274. Of course, they really meant

  275.     exit (1)

  276. or just

  277.     exit 1

  278. Either shell will complain about this.  But if you hide this in an if
  279. clause, like so:

  280.     #!/bin/csh -fn
  281.     if (1) then
  282.         exit (i)
  283.     endif

  284. The csh tells you there's nothing wrong with this script.  The equivalent
  285. construct in the Bourne shell, on the other hand, tells you this:


  286.     #!/bin/sh -n
  287.     if (1) then
  288.         exit (i)
  289.     endif

  290.     /tmp/x: syntax error at line 3: `(' unexpected



  291. RANDOM BUGS

  292. Here's one:

  293.     fg %?string
  294.     ^Z
  295.     kill  %?string
  296.     No match.

  297. Huh? Here's another

  298.     !%s%x%s

  299. Coredump, or garbage.

  300. If you have an alias with backquotes, and use that in backquotes in
  301. another one, you get a coredump.

  302. Try this:
  303.     % repeat 3 echo "/vmu*"
  304.     /vmu*
  305.     /vmunix
  306.     /vmunix
  307. What???


  308. Here's another one:

  309.     % mkdir tst
  310.     % cd tst
  311.     % touch '[foo]bar'
  312.     % foreach var ( * )
  313.     > echo "File named $var"
  314.     > end
  315.     foreach: No match.


  316. 8. SUMMARY


  317. While some vendors have fixed some of the csh's bugs (the tcsh also does
  318. much better here), many have added new ones.  Most of its problems can
  319. never be solved because they're not actually bugs per se, but rather the
  320. direct consequences of braindead design decisions.  It's inherently flawed.

  321. Do yourself a favor, and if you *have* to write a shell script, do it in the
  322. Bourne shell.  It's on every UNIX system out there.  However, behavior
  323. can vary.

  324. There are other possibilities.

  325. The Korn shell is the preferred programming shell by many sh addicts,
  326. but it still suffers from inherent problems in the Bourne shell's design,
  327. such as parsing and evaluation horrors.  The Korn shell or its
  328. public-domain clones and supersets (like bash) aren't quite so ubiquitous
  329. as sh, so it probably wouldn't be wise to write a sharchive in them that
  330. you post to the net.  When 1003.2 becomes a real standard that companies
  331. are forced to adhere to, then we'll be in much better shape.  Until
  332. then, we'll be stuck with bug-incompatible versions of the sh lying about.

  333. The Plan 9 shell, rc, is much cleaner in its parsing and evaluation; it is
  334. not widely available, so you'd be significantly sacrificing portability.
  335. No vendor is shipping it yet.

  336. If you don't have to use a shell, but just want an interpreted language,
  337. many other free possibilities present themselves, like Perl, REXX, TCL,
  338. Scheme, or Python.  Of these, Perl is probably the most widely available
  339. on UNIX (and many other) systems and certainly comes with the most
  340. extensive UNIX interface.  Increasing numbers vendors ship Perl with
  341. their standard systems.  (See the comp.lang.perl FAQ for a list.)

  342. If you have a problem that would ordinarily use sed or awk or sh, but it
  343. exceeds their capabilities or must run a little faster, and you don't want
  344. to write the silly thing in C, then Perl may be for you.  You can get
  345. at networking functions, binary data, and most of the C library. There
  346. are also translators to turn your sed and awk scripts into Perl scripts,
  347. as well as a symbolic debugger.  Tchrist's personal rule of thumb is
  348. that if it's the size that fits in a Makefile, it gets written in the
  349. Bourne shell, but anything bigger gets written in Perl.

  350. See the comp.lang.{perl,rexx,tcl} newsgroups for details about these
  351. languages (including FAQs), or David Muir Sharnoff's comparison of
  352. freely available languages and tools in comp.lang.misc and news.answers.
  353. --
  354.     Tom Christiansen      tchrist@cs.colorado.edu      
  355.                     Consultant
  356.         Boulder Colorado  303-444-3212





复制代码

论坛徽章:
0
4 [报告]
发表于 2006-05-08 23:00 |只看该作者
老大,这些是什么啊?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP