免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: haha1118
打印 上一主题 下一主题

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新) [复制链接]

论坛徽章:
0
21 [报告]
发表于 2003-03-13 01:46 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

原帖由 "红袖添香" 发表:
...

放心,能用能用,偶在Solaris下测试过。 :)


这回偶就放心了,偶用的也是Solaris。。。。谢谢红袖姐,那个什么。。滔滔江水。。。。。。。

论坛徽章:
0
22 [报告]
发表于 2003-03-13 11:19 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

郁闷!!还是不行!!
    偶试了一下
    set line='12xy    12'
      echo "$line"          输出     '12xy    12'
      printf "%s", $line  输出     12xy,12,
所以单独使用 set line='12xy    12'   赋值是对的,
单独使用awk "{ print $0}" $fnm    结果也是对的
一旦同时使用 set line=`awk "{ if (NR == $i) print}" $fnm` 就不对了!
    再看一个例子
    set line='12xy    12'
    set ff1  = `echo "$line" | awk '{printf "%s", "'\''" substr($$i,3,6) "'\''"}'`
按理说ff1的值应该是 'xy    '  (4个space)
但结果是   'xy '                  (1个space)!!!

     因此,偶认为问题出在set 与awk 结合使用时,这里真的没办法控制吗?

论坛徽章:
0
23 [报告]
发表于 2003-03-14 01:00 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

郁闷!!还是不行!! 偶要考虑是否要自裁了!!!
偶试了一下
set line='12xy 12'
echo "$line" 输出 '12xy 12'
printf "%s", $line 输出 12xy,12,
所以单独使用 set line='12xy 12' 赋值是对的,
单独使用awk "{ print $0}" $fnm 结果也是对的
一旦同时使用 set line=`awk "{ if (NR == $i) print}" $fnm` 就不对了!
再看一个例子
set line='12xy 12'
set ff1 = `echo "$line" | awk '{printf "%s", "'\''" substr($$i,3,6) "'\''"}'`
按理说ff1的值应该是 'xy ' (4个space)
但结果是 'xy ' (1个space)!!!

因此,偶认为问题出在set 与awk 结合使用时,这里真的没办法控制吗?

论坛徽章:
0
24 [报告]
发表于 2003-03-14 01:05 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

...

呵呵,不用制裁。换个shell好了。生活会美好得多…… ^_^

你换个shell是不是有困难,还是另有原因?

论坛徽章:
0
25 [报告]
发表于 2003-03-14 02:05 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

是一个项目,客户指定用CSHELL,只剩1周的时间了,。。。
主要的工作是从1个固定格式的文本文件中读数据去更新DB(有数值型也有字符型,没有分割符),。。。。。。
用CSHELL是不是真的没办法?给偶两个理由先,偶去申请换1个SHELL。。。
偶真的要绝望了。。。。

论坛徽章:
0
26 [报告]
发表于 2003-03-14 02:14 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

...

其实不用我帮你找,你在 google 中输入 buggy csh,然后搜索,你就能找到很多。

论坛徽章:
0
27 [报告]
发表于 2003-03-14 02:23 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

...

其实不用我帮你找,你在 google 中输入 buggy csh,然后搜索,你就能找到很多。

论坛徽章:
0
28 [报告]
发表于 2003-03-14 02:24 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

...

这里是其中的一篇,对 csh 的弊端讲得比较详细


csh programming considered harmful

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

The csh is seductive because the conditionals are more C-like, so the path of least resistance if chosen and a csh script is written.  sadly, This is
a lost cause, and they don't realize it, even when they find that the very simple things they wish to do are cumbersome or impossible in the csh.

Let me attempt to spell out some very good reasons why the csh is an utterly inadequate tool for programming and its use for such purposes
should be strictly banned.  I preface this from the tail of the csh man page on Suns:

    Although robust enough for general use, adventures
    into the esoteric periphery of the C shell may reveal
    unexpected quirks.

This is understatement at its finest, and should be in our man page, too.

So here's a document I wrote a while back elaborating on numerous very sound reasons why not to use the csh for programming.  I suspect that
after reading them you'll agree.  I shall put this in swnotes for safekeeping.

--tom


1.  EXPRESSION EVALUATION

    Consider this statement in the csh:


if ($?MANPAGER) setenv PAGER $MANPAGER


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

MANPAGER: Undefined variable.

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

if ($?MANPAGER) then
     setenv PAGER $MANPAGER
endif

    That's the same problem you have here:

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

    This forced to write a couple nested if's.  This is gross and stupid
    because it renders short-ciruit booleans useless.  If this were the
    really C-like, you would expect to be able to safely write such becuase
    of the common C construct:

if (p && p->member)

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


3.  ERROR HANDLING

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

exit (i)

    Of course, they really meant

exit (1)

    or just

exit 1

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

#!/bin/csh -fn
if (1) then
     exit (i)
endif

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


#!/bin/sh -n
if (1) then
     exit (i)
endif

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



3.  FILE DESCRIPTORS

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

3a. Writing Files

    In the Bourne shell, you can open or dup random file descriptors.
    For example,

exec 2>errs.out

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

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

cmd 2>/dev/null

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

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

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

3b. Reading Files

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

exec 3<file1
exec 4<file2

    Now you can read from fd 3 and get lines from file1, or from file2 through
    fd 4.   In modern bournelike shells, this suffices:

read some_var 0<&amp;3
read another_var 0<&amp;4

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

exec 5<&amp;0  # save old stdin
exec 0<&amp;3; read some_var
exec 0<&amp;4; read another_var
exec 0<&amp;5  # restore it


3c. Closing FDs

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

3d. More Elaborate Combinations

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

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

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

    Consider the pipeline:

A | B | C

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

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



4.  COMMAND ORTHOGONALITY

4a. Built-ins

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

  % time | echo

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

  Reset tty pgrp from 9341 to 26678

    Others are more fun:

  % sleep 1 | while
  while: Too few arguments.
  [5] 9402
  % jobs
  [5]     9402 Done                 sleep |


    Some can even hang your shell.  Try typing ^Z while you're sourcing
    something.  Or redirecting a source command.

4b. Flow control

    You can't mix flow-control and commands, like this:

who | while read line; do
     echo "gotta $line"
done

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

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


4c. Stupid non-orthogonal parsing bugs

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

kill -1 `cat foo`
`cat foo`: Ambiguous.

    But this is ok:

/bin/kill -1 `cat foo`

    There are many more of these.



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

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

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



6.  QUOTING

    You can't quote things reasonably in the csh:

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

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

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

    Dollar signs cannot be escaped in doublequotes in the csh.  Ug.

set foo = "this is a \$dollar quoted and this is $HOME not quoted"
dollar: Undefined variable.
   
    You have to use backslashes for newlines, and it's just darn hard to
    get them into strings sometimes.

set foo = "this \
and that";
echo $foo
this  and that
echo "$foo"
Unmatched ".  # say what???
echo $foo:q

    You don't have these problems in the Bourne shell, where it's just
    fine to write things like this:

echo  'This is
    some text that contains
   several newlines.'


7.  VARIABLES

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

    In Bourne shell, this
VAR=foo cmds args
     is the same as
(export VAR; VAR=foo; cmd args)
    or csh's
(setenv VAR;  cmd args)
   
    You can't use :t, :h, etc on envariables.  Watch:
     echo Try testing with $SHELL:t

    It's really nice to be able to say

${PAGER-more}
    or
FOO=${BAR:-${BAZ}}

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

    You can't get the process number of the last background
    command from the csh.  In the Bourne shell, it's $!.



7.  RANDOM BUGS

    Here's one:

fg %?string
^Z
kill  %?string
No match.

    Huh? Here's another

!%s%x%s

    Coredump, or garbage.

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

    Try this:
% repeat 3 echo "/vmu*"
/vmu*
/vmunix
/vmunix
    What???



    There are a lot, probably over 100, of these.

论坛徽章:
0
29 [报告]
发表于 2003-03-14 04:27 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

when I saw the name "红袖添香", I know it's the final answer.

论坛徽章:
0
30 [报告]
发表于 2003-03-14 08:48 |只看该作者

红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)

[quote]原帖由 "peter333"]when I saw the name "红袖添香", I know it's the final answer.[/quote 发表:

hoho~~~indetermination
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP