cat file | while read line的问题

或许你应该在其他脚本中见过下面的这种写法:

while read line

do

done < file

刚开始看到这种结构时,很难理解< file是如何与循环配合在一起工作的。因为循环内有很多条命令,而我们之前接触的重定向都是为一条命令工作的。这里有一个原则,这个原则掌握好了,这个问题就很简单了:

对循环重定向的输入可适用于循环中的所有需要从标准输入读取数据的命令;

对循环重定向的输出可适用于循环中的所有需要向标准输出写入数据的命令;

当在循环内部显式地使用输入或输出重定向,内部重定向覆盖外部重定向。

上面的while结构中,read命令是需要从标准输入中读取数据的。我们来详细了解一下read命令的用法吧,这个命令是shell脚本中使用频率最高的命令之一。

read

先来看一下read的命令语法:

read arg1 arg2 arg3 arg4 …

read是一个用来赋值的命令,它需要从标准输入获得值,然后把这些值按位置依次赋值给变量arg1、arg2、arg3、arg4…,输入的时候以空格作为字段分隔符。

read的一个最大特性是可以在脚本中产生交互,因为它从标准输入读取数据。read之所以很常用,一是因为我们经常需要赋值,二是因为它可以交互,三是read能够一次给多个变量赋值。

$ read host ip name

linux 10.0.0.1 licong

$ echo $host $ip $name

linux 10.0.0.1 licong

$

可以看到,linux、10.0.0.1、licong分别被赋值给了变量host、ip和name。再看:

$ read host ip

linux 10.0.0.1 licong

$ echo $host

linux

$ echo $ip

10.0.0.1 licong

$

当我们输入的字段比变量数目多时,最后一个变量的值将不只一个字段,而是所有剩余的内容;当输入字段比变量数少时,多余的变量将是空值,你可以自己试试。现在我们再来看

while read line

do

done < file

read通过输入重定向,把file的第一行所有的内容赋值给变量line,循环体内的命令一般包含对变量line的处理;然后循环处理file的第二行、第三行。。。一直到file的最后一行。还记得while根据其后的命令退出状态来判断是否执行循环体吗?是的,read命令也有退出状态,当它从文件file中读到内容时,退出状态为0,循环继续惊醒;当read从文件中读完最后一行后,下次便没有内容可读了,此时read的退出状态为非0,所以循环才会退出。

另一种也很常见的用法:

command | while read line

do

done

如果你还记得管道的用法,这个结构应该不难理解吧。command命令的输出作为read循环的输入,这种结构长用于处理超过一行的输出,当然awk也很擅长做这种事。

APP_FILE=./aabb(这个是多行文件)
cat $APP_FILE|while read line
do
    ssh -q $line ls /home/admin
done
fail: 只执行了一次,就退出了循环

这里的问题是所有的内容都一起读取出来写到缓存里面了,让SSH重定向出去了

注意:

1. ssh命令在每次执行时,会读取所有的标准输入中的内容。

cat file |ssh 1.1.1.1 cat  会读取所有文件的内容

2. 对于while循环,当按照如下方式使用时:

cat file | while read line

这里使用重定向,将文件内容输入到while命令,while命令每次使用read从输入中读取一行数据。

问题就在这里,如果在while循环中调用了ssh命令,那么ssh就会把当前输入中所有的数据读走,也就是cat file重定向给while命令的数据,都被ssh命令读走了,以至于下次循环的时候,read读到的内容为空,导致循环提前结束。

解决这个问题两种方式

1. ssh -n 使用-n参数

2. ssh xxxx < /dev/null重定向shell命令的输入

主要参数说明:

-l 指定登入用户

-p 设置端口号

-f 后台运行,并推荐加上 -n 参数

-n 将标准输入重定向到 /dev/null,防止读取标准输入

-N 不执行远程命令,只做端口转发

-q 安静模式,忽略一切对话和错误提示

-T 禁用伪终端配置

参考文章

http://blog.163.com/[email protected]/blog/static/11135225920118742327322/

一 、重定向法;管道法: cat $FILENAME | while read LINE

Function While_read_LINE(){

cat $FILENAME | while read LINE

do

echo $LINE

done

}

注释:我只所有把这种方式叫做管道法,相比大家应该可以看出来了吧。当遇见管道的时候管道左边的命令的输出会作为管道右边命令的输入然后被输入出来。

二、实例

1、pri.sh

#!/bin/bash

cat ~/xieco/dirls | while read dd
do
  echo "chown -R test:test ${dd}"
  chown -R deuser:deuser ${dd}
done

2、dirr

/usr/local/htdocs/dcserver/utilserver/
/usr/local/configs/

### 题目要求
计算文档a.txt中每一行中出现的数字个数并且要计算一下整个文档中一共出现了几个数字。例如a.txt内容如下:
12aa*lkjskdj
alskdflkskdjflkjj
我们脚本名字为 ncount.sh, 运行它时:
bash ncount.sh a.txt
输出结果应该为:
2
0
sum:2

#### 参考答案
```

#!/bin/bash

sum=0

while read line

do

line_n=`echo $line|sed ‘s/[^0-9]//g‘|wc -L`

echo $line_n

sum=$[$sum+$line_n]

done < $1

echo "sum:$sum"

  

当我们输入的字段比变量数目多时,最后一个变量的值将不只一个字段,而是所有剩余的内容;当输入字段比变量数少时,多余的变量将是空值,你可以自己试试。现在我们再来看

while read line

do

done < file

read通过输入重定向,把file的第一行所有的内容赋值给变量line,循环体内的命令一般包含对变量line的处理;然后循环处理file的第二行、第三行。。。一直到file的最后一行。还记得while根据其后的命令退出状态来判断是否执行循环体吗?是的,read命令也有退出状态,当它从文件file中读到内容时,退出状态为0,循环继续惊醒;当read从文件中读完最后一行后,下次便没有内容可读了,此时read的退出状态为非0,所以循环才会退出。

另一种也很常见的用法:

command | while read line

do

done

如果你还记得管道的用法,这个结构应该不难理解吧。command命令的输出作为read循环的输入,这种结构长用于处理超过一行的输出,当然awk也很擅长做这种事。

原文地址:https://www.cnblogs.com/klb561/p/11241651.html

时间: 2024-10-22 09:19:23

cat file | while read line的问题的相关文章

How to build .apk file from command line(转)

How to build .apk file from command line Created on Wednesday, 29 June 2011 14:32 If you don’t want to install a number of programs for building your Android project, this article is for you. You will need only JDK, the Android SDK platform tools and

cat &gt;file &lt;&lt; EOF

1.cat >file记录的是键盘输入,相当于从键盘创建文件,并且只能创建新文件,不能编辑已有文件.>是数据重导向,会将你输入的文本内容输出到file中. 2.cat <<EOF cat命令是linux下的一个文本输出命令,通常是用于观看某个文件的内容的:EOF是"end of file",表示文本结束符. 结合这两个标识,即可避免使用多行echo命令的方式,并实现多行输出的结果. [范例]             ##------>使用cat >

(C++) Assertion failed: !&quot;Bad error code&quot;, file VMem.c, line 715

(C++) Assertion failed: !"Bad error code", file VMem.c, line 715 Misc error. Full error message Assertion failed: !"Bad error code", file VMem.c, line 715 View a screenshot of this error message Cause IDE: C++ Builder 6.0 Project type:

cat &gt; file &lt;&lt; EOF 的用法

cat> 文件名<<eof 用来创建文件在这之后输入任何东西 都是在 文件里的输入完成之后EOF结尾 代表结束比如 cat > 1.txt <<eof12345eof 就是创建1.txt这个文件里面内容是 1 2 3 4 5 ============================================cat <<EOF与cat <<-EOF的区别(原文:http://blog.csdn.net/apache0554/article/d

Linux基础知识 ls date stat cat file echo

Linux中的发行版Centos 自学了一年多的Centos了,全是学的一些杂×××功法,没有系统性连贯性的从头到尾贯穿一遍,导致许多知识点都知道一些皮毛,就类似于什么都知道,但是什么都不精通一样.....而且呢还总是急于求成,特别的基于求成,可能是对现状的不满意.....,想尽快的换一份待遇好的工作...可是最近呢,找到了一套九阳神功,打算从头练起,把基础知识弄透彻了,不要在基于求成,因为基础的才是最关键的,后面所有高级应用都是基于前面的基础知识,万变不离其宗吧!例如后面的LVS 就是根据前面

File:isctype.c Line 68

刚接触DSP,拿来别人的代码,编译时,发现如下错误: 百思不得琪姐,一番调查之后,发现自己的工程worksapce中有中文路径,怎一个fuck了得. 原文地址:https://www.cnblogs.com/xiaojianliu/p/8643793.html

shell按行读取文件的方法

写法一: ---------------------------------------------------------------------------- #!/bin/bash while read line do echo $line done < filename(待读取的文件) ---------------------------------------------------------------------------- 写法二: --------------------

shell读取文件行,列

cat ${FILE} | while read line do echo $line done ------------------------------------------- while read LINE  #每次读取aa.list中的一行 do echo $LINE     #输出每行的信息 done < ${FILE} ------------------------------------------- 读取文件的每行第一列和第二列 while read n m do echo

shell脚本,一个字符一个字符输出。

[[email protected] wyb]# cat file 123 abc 456 456 def 1 23 5678 abc 789 789de f567 [[email protected] wyb]# cat fffile.sh #!/bin/bash cat file| while read line do for i in `seq 1 ${#line}` do a=`echo $line|cut -c $i` echo -ne "$a" sleep 0.1 done