温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Shell逐行处理文本求和的示例分析

发布时间:2021-06-12 09:22:42 来源:亿速云 阅读:263 作者:小新 栏目:web开发

这篇文章主要介绍Shell逐行处理文本求和的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

假设要要计算文本test.data的第二列的数字之和:

1 12  2 23  3 34  4 56

当然你可能会这样处理:

awk '{s+=$2} END {print s}' test.data

很快就得到了结果。不过,本文要说的点与awk无关。我们通过另外一种方式来计算,即逐行分析处理的方式。

尝试一

我们尝试第一种方式,shell实现如下:

#!/usr/bin/env bash sum=0 cat test.data | while read line do     temp_num=$(echo "$line" | cut -d ' ' -f 2)     sum=$(( $sum + $temp_num )) done echo "we get sum:$sum"

输出结果:

we get sum:0

这是为什么!为什么得到的结果会是0呢?

这事坏就坏在脚本中的|,众所周知,这是一个管道命令,而这也就意味着,while循环的执行结果都是在一个subshell中,一旦这个subsell退出了,它里面的结果也就没有了。

其实这个问题利用有了这个神器,再也不怕shell写得不对了中提到的工具很容易发现:

$ shellcheck myscript  Line 3: cat test.data | while read line     ^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.                       ^-- SC2162: read without -r will mangle backslashes.  Line 6:     sum=$(( $sum + $temp_num ))     ^-- SC2030: Modification of sum is local (to subshell caused by pipeline).             ^-- SC2004: $/${} is unnecessary on arithmetic variables.                    ^-- SC2004: $/${} is unnecessary on arithmetic variables.  Line 8: echo "we get sum:$sum"                  ^-- SC2031: sum was modified in a subshell. That change might be lost.  $

尝试二

既然管道命令不建议用,那么我们使用下面的方式看看:

#!/usr/bin/env bash sum=0 for line in $(cat test.data) do     echo "get line :$line"     temp_num=$(echo "$line" | cut -d ' ' -f 2)     sum=$(( $sum + $temp_num )) done echo "we get sum:$sum"

输出结果:

get line :1 get line :12 get line :2 get line :23 get line :3 get line :34 get line :4 get line :56 we get sum:135

从结果中看出,如果文本中存在空格或者tab等,则看似每次读取一行,实际上是遇到空格,tab或换行就停止读取了,并没有达到我们的目的。

我们预期的应该是遇到换行才停止读取,为了达到这个目的,我们可以设置这个标记,即通过设置IFS来达到目的。在上面的shell开头加上:

IFS=$'\n'

但是修改为这样之后,在自己的系统上并没有得到我想要的效果,有知道的读者可以告知一下。

尝试三

让我们再换一种方式:

#!/usr/bin/env bash sum=0 while read line do     echo "line $line"     temp_num=$(echo "$line" | cut -d ' ' -f 2)     sum=$(( $sum + $temp_num )) done < "test.data" echo "we get sum:$sum"

这种方式我们是能得到正确结果的。

当然,如果你要读取指定列,你还可以像下面这样做:

#!/usr/bin/env bash sum=0 while read col1 col2 do     sum=$(( $sum + $col2 )) done < "test.data" echo "we get sum:$sum"

其中col1,col2就分别代表了第一列,第二列,使用的时候,可以直接使用对应列的内容。

但是,如果我们要读取的内容包括了转义字符会怎么办?例如:

\n 12 \n 23 \n 34 \n 56

执行结果:

line   12 line   23 line   34 line   56 we get sum:125

从结果可以看到,虽然内容能否读取到,但是内容被打印出来的时候,已经变了,\被当成转义字符处理了,如果不想让它转义处理怎么办?只需要加上-r参数即可:

while read -r line

总结

在逐行处理文本过程中,主要关注以下几种情况:

  • 行中有空格,tab

  • 行中有转义字符

另外,通过shellcheck工具也会发现,它并不推荐for in file这种方式逐行处理文本:

Line 3: for line in $(cat test.data)             ^-- SC2013: To read lines rather than words, pipe/redirect to a 'while read' loop.

以上是“Shell逐行处理文本求和的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI