shell - 为什么使用 cut 比 awk 从文件中的每一行截取两个字符串要慢得多?
问题描述
我有一个大约 160 万行的文件,每行大约
2018_08_01_02_00_00_OL13F1i5014j2513,0
2018_08_01_02_00_00_OL13F1i5055j2490,0
文件名为 order_all.csv。
现在我有两个脚本
外壳一
#!/bin/bash
while read line
do
st="set "
key="$(echo $line | cut -d',' -f1)"
value="$(echo $line | cut -d',' -f2)"
echo "$st$key $value" >> output
done < order_all.csv
外壳二
cat order_all.csv | awk -F ',' '{print "set " $1,$2}' > output
但是我发现第二个脚本比第一个快得多。什么原因?另外,我也希望脚本输出的每一行的换行符都是\r\n。我能做些什么呢?
解决方案
正如@zerkms 所说,这里的性能差异更多地取决于算法的效率,而不是正在运行的文本处理命令。
要了解两者之间的差异,您需要了解 shell 与大多数其他语言相比的工作方式。由于 shell 基本上是一个一个地执行的单个 unix 程序,因此每一行(实际上是命令)的性能是另一种语言的整个程序的性能,其他一切都相同。
这相当于在这里,通过围绕每一行数据构建一个循环,然后执行一个命令,“cut”,你承担了为每一行数据启动一个新程序的开销(在这种情况下为 2,因为你叫 cut 2 次)。
执行任何 unix 命令的单个实例的幕后都是一些非常昂贵的操作系统调用,这些调用需要花费大量时间,例如 fork(),更不用说将命令加载到内存中的过程以及那里涉及的所有内容。
在您的第二个版本中,您巧妙地避免使用管道“|”为每一行文本启动新命令。该管道将数据流式传输到“awk”。在此设计中,Awk 仅启动一次,因为它一次从 STDIN 读取一行,直到遇到流中的文件结尾。'cut' 也可以以这种方式工作(在流中),但处理文本在 'cut' 中受到更多限制。因此,这里的文本处理发生在一个进程中,awk 程序加载和 fork 开销只完成了一次,而文本处理发生了 160 万次。
我希望这会有所帮助。
推荐阅读
- http - 关于 http 设置“覆盖主机名”和“从后端地址选择主机名”中的选项的问题
- php - 显示在编辑页面中选中的复选框(PHP)
- flutter - 使用颤振在列表视图中搜索和选择项目
- reactjs - 使用 redux saga 等待某个时间点的正确方法?
- angular-material - Mat Tables:有没有办法设置两个标题,一个是垂直的,另一个是水平的?
- r - R编程中的download.file
- math - 在网站的离线副本中渲染数学
- c# - 关闭在用户控件中打开的一个或多个窗体
- c# - Datagridview 第二次对 bindingsource 完全隐藏
- javascript - NodeJS 中的警报(没有任何延迟)