【问题标题】:Replacing awk with bash built-ins用 bash 内置函数替换 awk
【发布时间】:2014-02-14 14:30:35
【问题描述】:

我被告知要编写一个 bash 脚本,用于在“/etc/passwd”文件中添加所有 GroupID,这是我的脚本

 #!/bin/sh
 # script input should be (sh groupsum.sh /etc/passwd)

 if [ -f $1 ] ; then
     awk -F ':' '{print $4}' $1 > /tmp/numb
     A=`awk '{s+=$1} END {print s}' /tmp/numb`
     echo $A
 else
     echo "its not a file"
 fi

脚本运行良好,但为了加快速度,我应该使用 bash 内置命令,而不是使用“awk”。所以我需要使用内置命令来实现这一点的信息,如果有人对此给出解释,那就太好了。

【问题讨论】:

  • 我认为awk -F: '{print s+=$4} END{print s}' /etc/passwd 相当快。
  • 你真的需要这样做很多次,以至于原生 bash 与 awk 的性能很重要吗?
  • 将组 ID 添加在一起有什么可能的用途?听起来像是一个设计不佳的家庭作业。

标签: linux bash shell awk


【解决方案1】:

您说的是“内置 bash”,但您的脚本以 #!/bin/sh 开头——它请求 POSIX sh,而不是 bash。不过,我假设您真的确实想要 bash。

#!/bin/bash
[[ -f "$1" ]] || { echo "Not a file" >&2; exit 1; }
exec <"$1"
total=0
while IFS=':' read -r _ _ _ groupid _; do
  (( total += groupid ))
done
echo "$total"

解释用于替换 awk 脚本组件的具体操作:read 命令遍历行(默认情况下),用IFS 中的字符分割它们;所以IFS=: read -r _ _ _ groupid _ 丢弃前三列,将第四列放入名为groupid 的变量中,然后丢弃其余列。 (( )) 是 bash 中的数学上下文;在其中,C 风格的语法可用于整数算术运算,因此是加法。


顺便说一句,直接读取/etc/passwd 是个坏主意——它不适用于使用LDAP、NIS 或任何其他替代目录服务的系统。如果您在 Linux 主机上,则可以使用 getent 程序进行查找,以适用于您当前的目录服务:

$ yourscript <(getent passwd)

话虽如此,这个问题的前提是一个糟糕的问题 - 尽管生成任何外部程序(包括 awk)都会产生开销,但一旦它运行,awk 比 bash 快得多。如果速度是您的唯一优先事项,您最好不要使用 shell,并让您的脚本以直接运行 awk 解释器的 shebang 开头。

【讨论】:

  • 有人告诉我不要从脚本创建子进程我们正在使用的 Unix 操作系统。
  • @PrabhuAre,如果将 awk 作为子进程运行太贵,那么无论如何使用 bash 可能太贵了。我会考虑将其编写为纯 awk 脚本(#!/usr/bin/awk -f 而不是 #!/bin/bash#!/bin/sh),因此您运行 awk,而不是启动 bash 并让它启动 awk,这将是比 only 运行 bash 更快,就像这里的脚本一样。
猜你喜欢
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 2015-04-01
  • 2019-08-07
  • 2019-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多