Chinaunix

标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新) [打印本页]

作者: haha1118    时间: 2003-03-07 00:57
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
用下面的方法:
foreach i ( `cat file.txt`)
echo $i
end

一般情况是可以的,但是如果有空格就不行了(1行被分成多行)。

不知各位大虾有何高见?
作者: haha1118    时间: 2003-03-07 16:45
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
俺试了以下方法:
foreach i ('12 34' '34 56')
echo $i
end
结果是正确的:
12 34
34 56

但是俺稍微改了一下:
foreach i (`echo "a" | awk '{print "'\''" $0 "'\''" }' $fnm `)
echo $i
end
结果是:
'12
34'
'34
56'

请教各位大虾
作者: 流浪着的鱼    时间: 2003-03-07 19:36
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
用while read不用for 可取一行
作者: 流浪着的鱼    时间: 2003-03-07 19:37
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
用while read不用for 可取一行
作者: 阿骁    时间: 2003-03-07 19:47
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
这是bsh的一个逐行读取的例子,你可以参考一下。

j=0
len=`wc -l < $infile`
while test $j -lt $len;
do
        a=`tail +$j $infile | head -1`
        …$a holds line of data…
        j=`expr $j + 1`
done
作者: 红袖添香    时间: 2003-03-07 22:49
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...


csh 这方面很弱,不好处理。我对 csh 不熟,也没有很好的办法,也许

1、你可以用 awk,对每一行的处理在 awk 环境中完成
awk "{print}" file.txt

2、如果不能或不想在 awk 中处理,试试这样,也可以在 csh 环境中完成

  1. #!/bin/csh
  2. set i = 0
  3. set l = `awk 'END{print NR}' file.txt`   # 总行数
  4. while ( $i <= $l )
  5.     set line=`awk "{ if (NR == $i) print}" file.txt`
  6.     echo $line   
  7.     ...  # 任何对 $line 的处理应用
  8.     @ i ++
  9. end
复制代码


祝好运,写 csh 比写 sh, ksh 要痛苦好几倍,
作者: nmgzw    时间: 2003-03-08 09:17
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
红袖姐写的这个me看明白了,应该是什么shell下都好使吧!只要有awk!
作者: 红袖添香    时间: 2003-03-08 11:55
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
[quote]原帖由 "nmgzw"]红袖姐写的这个me看明白了,应该是什么shell下都好使吧!只要有awk![/quote 发表:


对的。

如果不使用awk,将会很麻烦!

而且楼主的二楼的帖子中也是用了awk的。所以……
作者: haha1118    时间: 2003-03-09 18:41
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
红袖姐的方法俺试过了,这回是彻底解决了

谢谢红袖姐!谢谢各位大虾!俺的热泪如滔滔江水。。。。。

难题一朝而解,快何如之!
作者: 木刀客    时间: 2003-03-09 19:47
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
红袖你真是mm?

看到你的帖字
真的有亲切感。(我有病?)
作者: 红袖添香    时间: 2003-03-10 05:35
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...

第一个问号:不可以吗?

第二个问号:呵呵,答不上来。
作者: laoxia    时间: 2003-03-10 07:32
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
原帖由 "木刀客" 发表:
红袖你真是mm?

看到你的帖字
真的有亲切感。(我有病?)
好好看书,不许早恋!

以一个过来N次的人的身份告诉你,早恋酿苦果哦
作者: nkliyong    时间: 2003-03-10 09:26
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
原帖由 "laoxia" 发表:
煤每词椋?恍碓缌担?

以一个过来N次的人的身份告诉你,早恋酿苦果哦


更俺说说什么苦果?
作者: laoxia    时间: 2003-03-10 09:31
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
原帖由 "nkliyong" 发表:


更俺说说什么苦果?
俺第一个女朋友都上高三了,俺还在初中
作者: nmgzw    时间: 2003-03-10 09:47
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...........





-------------------------------------------------
打死你,让你小子灌水........
作者: haha1118    时间: 2003-03-12 11:51
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
不好意思,还有问题,请各位大虾指点是否还有活路?

运行:
#!/bin/csh
set i = 0
set l = `awk 'END{print NR}' file.txt`   # 总行数
while ( $i <= $l )
    set line=`awk "{ if (NR == $i) print}" file.txt`
    echo $line   
    ...  # 任何对 $line 的处理应用
    @ i ++
end

当存在多个空格连续的情况,输出给合并成1个,例:
12              (n个space)456                    (n个space)789
输出:
12 (1个space)456 (1个space)789

郁闷!!
作者: haha1118    时间: 2003-03-13 00:32
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
不好意思,还有问题,请各位大虾指点是否还有活路?

运行:
#!/bin/csh
set i = 0
set l = `awk 'END{print NR}' file.txt` # 总行数
while ( $i <= $l )
set line=`awk "{ if (NR == $i) print}" file.txt`
echo $line
... # 任何对 $line 的处理应用
@ i ++
end

当存在多个空格连续的情况,输出给合并成1个,例:
12 (n个space)456 (n个space)789
输出:
12 (1个space)456 (1个space)789

郁闷!!
作者: 红袖添香    时间: 2003-03-13 00:37
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...



哦,上次没考虑到你这个要求

不要郁闷,很好办的,:)

把 echo $line 改为 printf "%s", $line 就可以了。

(希望能够解决问题,现在我要出一下门,大约半个小时后才能再回来)
作者: haha1118    时间: 2003-03-13 00:54
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
原帖由 "红袖添香" 发表:
...

把 echo $line 改为 printf "%s", $line 就可以了。

(希望能够解决问题,现在我要出一下门,大约半个小时后才能再回来)


谢谢红袖姐,偶现在没办法试。只能等明天上班。。。。
printf 在cshel下能用吗?偶没查到啊
作者: 红袖添香    时间: 2003-03-13 01:06
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...

放心,能用能用,偶在Solaris下测试过。 :)
作者: haha1118    时间: 2003-03-13 01:46
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
原帖由 "红袖添香" 发表:
...

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


这回偶就放心了,偶用的也是Solaris。。。。谢谢红袖姐,那个什么。。滔滔江水。。。。。。。
作者: haha1118    时间: 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 结合使用时,这里真的没办法控制吗?
作者: haha1118    时间: 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 结合使用时,这里真的没办法控制吗?
作者: 红袖添香    时间: 2003-03-14 01:05
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...

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

你换个shell是不是有困难,还是另有原因?
作者: haha1118    时间: 2003-03-14 02:05
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
是一个项目,客户指定用CSHELL,只剩1周的时间了,。。。
主要的工作是从1个固定格式的文本文件中读数据去更新DB(有数值型也有字符型,没有分割符),。。。。。。
用CSHELL是不是真的没办法?给偶两个理由先,偶去申请换1个SHELL。。。
偶真的要绝望了。。。。
作者: 红袖添香    时间: 2003-03-14 02:14
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...

其实不用我帮你找,你在 google 中输入 buggy csh,然后搜索,你就能找到很多。
作者: 红袖添香    时间: 2003-03-14 02:23
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
...

其实不用我帮你找,你在 google 中输入 buggy csh,然后搜索,你就能找到很多。
作者: 红袖添香    时间: 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 &amp;&amp; $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 &amp;&amp; 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) >&amp; /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.
作者: peter333    时间: 2003-03-14 04:27
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
when I saw the name "红袖添香", I know it's the final answer.
作者: i2era    时间: 2003-03-14 08:48
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
[quote]原帖由 "peter333"]when I saw the name "红袖添香", I know it's the final answer.[/quote 发表:

hoho~~~indetermination
作者: haha1118    时间: 2003-03-15 00:42
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
偶终于“圆满”了!终于可以不用CSHELL了!
I have a dream! 让cshell见鬼去吧!
偶用SHELL是这样实现的,大家提提意见
#!/bin/sh

awk '{print substr($0,1,5),      \
                   substr($0,6,6)}'    \
                   a.txt |                    \
while read Fld1                  \
                  Fld2
do
    echo $Fld1,$Fld2

....
done

偶要感谢红袖姐,红袖姐是在北京吗?偶请客!
作者: 红袖添香    时间: 2003-03-17 23:23
标题: 红袖添香救我呀:用cshell怎么逐行读文件逐行处理?(新)
原帖由 "haha1118" 发表:
偶终于“圆满”了!终于可以不用CSHELL了!
I have a dream! 让cshell见鬼去吧!
偶用SHELL是这样实现的,大家提提意见
#!/bin/sh

awk '{print substr($0,1,5),      \
                   substr($0,6,6)}' ..........


shell和awk的组合挺灵活,怎么都行,看你自己的爱好了. 可以象你那样, 也可以while 在外面,  awk  在里面...

我要恭喜你啊。脱离苦海。。。

“让cshell见鬼去吧!”

看到这句话,我真想笑。它让我想起了丘吉尔的典故,呵呵。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2