shell: shell读取文本

shell scott 288℃ 0评论

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

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

a
b
c
d
#e
f
g

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

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

set -x

WR="account >"

while read line
do
    WR="$WR>"" >""$line>"
done<a.txt

echo $WR

最终我们看到输出的结果就是我们期待的 account a b c d #e f g

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+ 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的方式进行读入,但是得到的结果却不是我们期望的

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

set -x

WR="account >"

grep -v ^# a.txt | while read line
do
    WR=${WR}" >"${line}
done

echo $WR

最终的输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ 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循环的方式来进行处理:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

set -x

WR="account >"

for line in `grep -v ^# a.txt`
do
    WR=${WR}" >"${line}
done

echo $WR

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+ 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语句放到同一个子进程中。 如下 (请注意其中的 括号
):

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

set -x

declare -x WR="account >"

grep -v ^# a.txt | ( while read line
do
    WR=${WR}" >"${line}
done

echo $WR )

得到结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ 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读取文本/

转载请注明:osetc.com » shell: shell读取文本

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址