我正在以表单的形式编写脚本
while read LINE
do
[[ $LINE =~ ^headertag1 ]] && function1 && continue
[[ $LINE =~ ^headertag2 ]] && function2 && continue
...
done < filename
随着标签数量的增加,我将每行进行太多检查。我可以尝试将通用标签向上排序,但是我认为这不能解决基本问题。我不是软件工程师。是否有可以改善这种情况的编程概念/方法?
不确定此处,但是如果您希望整理代码并通过重复添加这些后卫感到无聊,那么也许这个想法会有所帮助:
#!/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是否在问这样的事情。
是,对于两个,您首先可以找到两者的最长公共前缀(这里的人们想知道如何在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。
[comment中的建议,我们可以考虑仅使用带有更简单的正则表达式的标签,并将其用作关联数组的键,该键在Bash中进行了优化(我们可以研究如何在源中满足我们的需求:
[如果我们知道它用-分隔的话,例如,如果我们知道它总是紧随我的:
或其他东西而没有包含它,请使用更简单的正则表达式,例如:
[[ $LINE =~ ^(.*): ]] && "${DICTIONARY_OF_FUNCTIONS["${BASH_REMATCH[1]}"]}"
如果所有标签都是/[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}"
}
您在每个标签上执行的测试
[[ $LINE =~ ^headertag1 ]] && function1 && continue
非常便宜(在内存正则表达式中。很可能,与读取LINE(从文件或其他进程中读取)相关的IO时间仅占一小部分。除非您进行大量测试,否则此实现是合理。
关于样式的注释:如果所有模式都是前缀匹配(或其他简单结构),请考虑使用bash
case语句
case "$LINE" in
header1*) function1 ;;
header2*) function2 ;;
...
esac
这将使代码更加优雅,但不会改变性能-RE和通配符都很简单。