![sed 和 awk 是否提供了我在 bash 脚本中使用普通 bash 无法轻松完成的任何操作?](https://linux22.com/image/181155/sed%20%E5%92%8C%20awk%20%E6%98%AF%E5%90%A6%E6%8F%90%E4%BE%9B%E4%BA%86%E6%88%91%E5%9C%A8%20bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%99%AE%E9%80%9A%20bash%20%E6%97%A0%E6%B3%95%E8%BD%BB%E6%9D%BE%E5%AE%8C%E6%88%90%E7%9A%84%E4%BB%BB%E4%BD%95%E6%93%8D%E4%BD%9C%EF%BC%9F%20.png)
我在学习 sed 和 awk 之前先学了 bash。我看到人们使用 sed、awk、有时甚至 grep 来完成很多事情,但我似乎只能使用 bash 逻辑来完成。我在想sed 和 awk 的哪些用例对于已经是 bash 脚本编写者的学习来说很有用?如果不完全了解 sed 和 awk,则很难确定这一点。
答案1
这有点像问如果你已经知道如何用手和膝盖爬行,那么学习如何驾驶汽车是否还有意义。是的,bash 可以被滥用于一些基本的文本操作或简单的数学,但它是最慢的工具,语法很复杂,而且非常非常容易出错。此外,包括 bash 在内的 shell 无法进行浮点运算,这极大地限制了仅使用 shell 所能实现的功能。
这些原因中的任何一个就足够了,但这里有一个非常简单的例子。取一个文件,该文件只不过是将 1 到 100,000 的数字按随机顺序打乱:
seq 100000 | shuf > file
现在,让我们选择所有奇数。在 bash 中,你可以这样做:
$ time while read num; do [[ $num =~ [24680]$ ]] || echo $num; done < file > newfile
real 0m3.481s
user 0m2.648s
sys 0m0.801s
在我的机器上大约需要 3 秒。如果我们做同样的事情,但数字在 1 到 1,000,000 之间怎么办?
seq 1000000 | shuf > file
和:
$ time while read num; do [[ $num =~ [24680]$ ]] || echo $num; done < file > newfile
real 0m32.483s
user 0m25.035s
sys 0m7.343s
这已经超过30秒了!现在,比较一下awk
可以进行正确数学运算的相同事物:
$ time awk '$1 % 2 !=0' file > newfile
real 0m0.344s
user 0m0.340s
sys 0m0.003s
不到一秒钟。 sed 怎么样,使用相同的文本匹配方法/
$ time sed -n '/[13579]$/p' file > newfile
real 0m0.280s
user 0m0.273s
sys 0m0.007s
不到一秒,又是一次。那么如果我们增加到 10,000,000 又如何呢?
$ seq 1000000 | shuf > file
$ time awk '$1 % 2 !=0' file > newfile
real 0m4.081s
user 0m3.896s
sys 0m0.090s
$ time sed -n '/[13579]$/p' file > newfile
real 0m2.898s
user 0m2.683s
sys 0m0.111s
$ time while read num; do [[ $num =~ [24680]$ ]] || echo $num; done < file > newfile1
real 5m42.445s
user 4m25.687s
sys 1m15.241s
正如您所看到的,shell 解决方案比非 shell 解决方案慢几个数量级。而一个1000万行的文件并不是什么特别罕见的事情。这只是一个76M的文本文件。此外,两种非 shell 解决方案都短得多(就字符长度而言),并且一旦您了解了它们的语法,就会简单得多。
所以,这就是“当你只有一把锤子时,一切看起来都像钉子”的情况。是的,bash 可以做一些你可以使用sed
或 之类的工具做的事情,awk
但它速度慢得多,而且做得不太好。