【问题标题】:Speed up bash filter function to run commands consecutively instead of per line加速 bash 过滤器功能以连续运行命令而不是每行
【发布时间】:2012-10-31 12:27:16
【问题描述】:

我在我的 ~/.bash_profile 中编写了以下过滤器作为函数:

hilite() {
 export REGEX_SED=$(echo $1 | sed "s/[|()]/\\\&/g")
 while read line
 do
  echo $line | egrep "$1" | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"
 done
 exit 0
}

查找与正则表达式匹配的任何内容的行,并在兼容 VT100 的终端上使用 ANSI 转义码突出显示匹配项。

例如,以下查找并突出显示字符串 binU1,它们是 / 的最后 10 行中的整个单词等/密码:

tail /etc/passwd | hilite "\b(bin|[U1])\b"

但是,脚本运行非常缓慢,因为每一行都分叉了一个 echo、egrep 和 sed。

在这种情况下,对整个输入执行 egrep,然后在其输出上运行 sed 会更有效。

如何修改我的函数来做到这一点?如果可能,我宁愿不创建任何临时文件。

附:有没有其他方法可以以类似的方式查找和突出显示线条?

【问题讨论】:

标签: bash shell filter highlighting grep


【解决方案1】:

sed 可以自己做一些 grepping:如果你给它-n 标志(或脚本中的#n 指令)它不会回显任何输出,除非被要求。所以

while read line
 do
  echo $line | egrep "$1" | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"
 done

可以简化为

sed -n "s/$REGEX_SED/\x1b[7m&\x1b[0m/gp"

编辑: 这是整个函数:

hilite() { 
    REGEX_SED=$(echo $1 | sed "s/[|()]/\\\&/g");
    sed -n "s/$REGEX_SED/\x1b[7m&\x1b[0m/gp"
}

仅此而已 - 没有 while 循环、读取、grepping 等。

【讨论】:

  • 不,不需要 egrep。使用-np 标志的全部意义在于不打印任何内容,除非它匹配。这与 grep 完全相同。 sed -n '/foo/p' 只是写grep foo 的另一种方式。
【解决方案2】:

如果您的egrep 支持--color,只需将其放入 .bash_profile:

  hilite() { command egrep --color=auto "$@"; }

(我个人将函数命名为egrep;因此使用command)。

【讨论】:

【解决方案3】:

我认为您可以简单地替换整个 while 循环

sed -n "s/$REGEX_SED/\x1b[7m&\x1b[0m/gp"

因为sed 可以逐行读取标准输入,所以您不需要read

我不确定运行egrep 和管道到sed 是否比单独使用sed 更快,但您始终可以使用time 进行比较。

编辑:将-np 添加到sed 以仅打印突出显示的行。

【讨论】:

  • 通过简单地使用-n 选项并为s 命令设置p 标志来解决此问题
【解决方案4】:

嗯,你可以这样做:

egrep "$1" $line | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"

但我不确定它会快得多; )

【讨论】:

  • 我不知道,但与egrepsed 相比,echo 在资源上可能要轻得多。无论如何,egrep 不会将$line 视为要在您编写的命令行中解析的文件吗?
  • 对不起,语法是 egrep 作为 doubleDown 注释。
【解决方案5】:

仅作记录,这是一种使用临时文件的方法:

hilite() {
 export REGEX_SED=$(echo $1 | sed "s/[|()]/\\\&/g")
 export FILE=$2
 if [ -z "$FILE" ]
 then
  export FILE=~/tmp
  echo -n > $FILE
  while read line
  do
   echo $line >> $FILE
  done
 fi
 egrep "$1" $FILE | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"
 return $?
}

它也将文件/路径名作为第二个参数,例如

cat /etc/passwd | hilite "\b(bin|[U1])\b"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多