Skip to content Skip to main navigation Skip to footer

shell: shell读取文本

都是使用shell自建的命令进行读取,可实际的结果会有很大的差异。

我们先建立一个测试文件a.txt

a
b
c
d
#e
f
g

然后进行字符串自增的方式进行测试。第一个使用重定向<符号来进行读入文件。

#!/bin/bash
set -x
WR="account >"
while read line
do
	WR="$WR>"" >""$line>"
done<a.txt
echo $WR &#91;/code&#93;
<p>最终我们看到输出的结果就是我们期待的 account a b c d #e f g</p>

+ WR='account '
+ read line
+ WR='account  a'
+ read line
+ WR='account  a b'
+ read line
+ WR='account  a b c'
+ read line
+ WR='account  a b c d'
+ read line
+ WR='account  a b c d #e'
+ read line
+ WR='account  a b c d #e f'
+ read line
+ WR='account  a b c d #e f g'
+ read line
+ echo account a b c d '#e' f g
account a b c d #e f g 

然后我们使用管道和while的方式进行读入,但是得到的结果却不是我们期望的

#!/bin/bash
set -x
WR="account >"
grep -v ^# a.txt | while read line
do
	WR=${WR}" >"${line}
done
echo $WR 

最终的输出为:

+ WR='account '
+ grep -v '^#' a.txt
+ read line
+ WR='account  a'
+ read line
+ WR='account  a b'
+ read line
+ WR='account  a b c'
+ read line
+ WR='account  a b c d'
+ read line
+ WR='account  a b c d f'
+ read line
+ WR='account  a b c d f g'
+ read line
+ echo account
account 

这样的方式,最终的输出居然只有“account”, 而没有别的内容,也就是只有我们初始化的那个内容,可打开调试我们可以看到明明最后一次自增后的结果是对的,可最终输出的值却不是我们想要的。

本来使用这种方式想处理a.txt这样的文本再传入给read,可最终结果既然不是我们想要的,那就用别的吧。 而重定向导入文件的方式是不能对文件进行在外部进行处理的,只能在while循环内部进行。

于是我们就用最后一个中for循环的方式来进行处理:

#!/bin/bash
set -x
WR="account >"
for line in `grep -v ^# a.txt`
do
	WR=${WR}" >"${line}
done
echo $WR 

最终的输出结果我们所期望的。

+ WR='account '
++ grep -v '^#' a.txt
+ for line in '`grep -v ^# a.txt`'
+ WR='account  a'
+ for line in '`grep -v ^# a.txt`'
+ WR='account  a b'
+ for line in '`grep -v ^# a.txt`'
+ WR='account  a b c'
+ for line in '`grep -v ^# a.txt`'
+ WR='account  a b c d'
+ for line in '`grep -v ^# a.txt`'
+ WR='account  a b c d f'
+ for line in '`grep -v ^# a.txt`'
+ WR='account  a b c d f g'
+ echo account a b c d f g
account a b c d f g 

而最终这个结果才是我们真正想要达到的结果。

至于为什么grep -v ^# a.txt | while read line这种方式不行呢? 这个是由于管道造成的。在管道的时候是fork了shell子进程,只有在子进程内这个值才是我们所期待的。 当然我们也可以把最后一个echo语句放到同一个子进程中。 如下 (请注意其中的 括号
):

#!/bin/bash
set -x
declare -x WR="account >"
grep -v ^# a.txt | ( while read line
do
	WR=${WR}" >"${line}
done
echo $WR ) 

得到结果如下:

+ declare -x 'WR=account '
+ grep -v '^#' a.txt
+ read line
+ WR='account  a'
+ read line
+ WR='account  a b'
+ read line
+ WR='account  a b c'
+ read line
+ WR='account  a b c d'
+ read line
+ WR='account  a b c d f'
+ read line
+ WR='account  a b c d f g'
+ read line
+ echo account a b c d f g
account a b c d f g 

而用重定向的方式就会受很多限制,记得只能是重定向文件,而不能是某个命令的结果。

所以综上所述,我们在做这样的操作的时候要注意管道和子进程的问题。 而且当我们读入的文件不是用n来分割的话,可以使用read 加参数的方式,或者直接先用awk进行处理。


shell读取文本
byTimo is my oasis is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License
.

原文:http://timo.piqiu.me/2015/04/22/shell读取文本/

0 Comments

There are no comments yet

Leave a comment

Your email address will not be published.