在遍历文件时优化行的前缀检查

问题描述 投票:0回答:3

我正在以表单的形式编写脚本

while read LINE 
do
    [[ $LINE =~ ^headertag1 ]] && function1 && continue
    [[ $LINE =~ ^headertag2 ]] && function2 && continue
    ...
done < filename

随着标签数量的增加,我将每行进行太多检查。我可以尝试将通用标签向上排序,但是我认为这不能解决基本问题。我不是软件工程师。是否有可以改善这种情况的编程概念/方法?

bash while-loop prefix prefix-tree
3个回答
1
投票

不确定此处,但是如果您希望整理代码并通过重复添加这些后卫感到无聊,那么也许这个想法会有所帮助:

#!/bin/bash

tags[tag1]="some regex1"
tags[tag2]="some regex2"
tags[tag3]="some regex3"

function action() {
  echo "perl -pe '${tags[$tag]} other-file.txt'"
}

while read LINE; do
  for tag in "${!tags[@]}"; do
    [[ $LINE =~ ^$tag ]] && action "${tags[$tag]}"
  done
done < filename

不确定OP是否在问这样的事情。


1
投票

是,对于两个,您首先可以找到两者的最长公共前缀(这里的人们想知道如何在Bash Longest common prefix of two strings in bash中做到这一点),然后首先检查行是否以它开头,然后从两个标签中将其剥离然后检查该行是否以其余部分开头。

超过两个,您需要创建一个特里树-也称为前缀树https://en.wikipedia.org/wiki/Trie

该维基百科文章说

有关前缀树的空间优化表示,请参见compact prefix tree

并且具有longest通用前缀,这就是您要拥有的。

Bash doesn't have multidimensional associative arrays起,您将不得不考虑https://en.wikipedia.org/wiki/Trie#Implementation_strategies或嵌入其他脚本语言,例如Perl或Python或GNU Awk(gawk),与标准Awk不同,introduces multidimensional associative arrays

使用Bash关联数组实现的优化

[comment中的建议,我们可以考虑仅使用带有更简单的正则表达式的标签,并将其用作关联数组的键,该键在Bash中进行了优化(我们可以研究如何在源中满足我们的需求:

[如果我们知道它用-分隔的话,例如,如果我们知道它总是紧随我的:或其他东西而没有包含它,请使用更简单的正则表达式,例如:

[[ $LINE =~ ^(.*): ]] && "${DICTIONARY_OF_FUNCTIONS["${BASH_REMATCH[1]}"]}"

使用Bash函数存储的优化

如果所有标签都是/[a-z][a-z0-9]+/,或者被Bash接受为其他函数名称,那么您可以使用上述方法插入函数名称,例如,

function the_function_for_tag_headertag1() {
    echo "hey it's the first one"
}
[[ $LINE =! ^(.*): ]] && {
    func_name="the_function_for_tag_${BASH_REMATCH[1]}"
    type "${func_name}" && "${func_name}"
}

1
投票

您在每个标签上执行的测试

    [[ $LINE =~ ^headertag1 ]] && function1 && continue

非常便宜(在内存正则表达式中。很可能,与读取LINE(从文件或其他进程中读取)相关的IO时间仅占一小部分。除非您进行大量测试,否则此实现是合理。

关于样式的注释:如果所有模式都是前缀匹配(或其他简单结构),请考虑使用bash case语句

case "$LINE" in
   header1*) function1 ;;
   header2*) function2 ;;
   ...
esac

这将使代码更加优雅,但不会改变性能-RE和通配符都很简单。

© www.soinside.com 2019 - 2024. All rights reserved.