Arrays 基于变量和第n个字符的数组解析

Arrays 基于变量和第n个字符的数组解析,arrays,bash,Arrays,Bash,希望能够基于变量解析数组,并获取接下来的2个字符 array=( 7501 7302 8403 9904 ) 如果var=73,则所需结果为02 如果var=75,则所需结果为01 如果var=84,则所需结果为03 如果var=99,则所需结果为04 如果这是一个基本问题,很抱歉,但我尝试过cut和grep的变体,但找不到解决方案 非常感谢您的帮助。您可以使用printf和awk使用此搜索功能: srch() { printf "%s\n" "${array[@]}" | awk -

希望能够基于变量解析数组,并获取接下来的2个字符

array=( 7501 7302 8403 9904 )
如果var=73,则所需结果为02
如果var=75,则所需结果为01
如果var=84,则所需结果为03
如果var=99,则所需结果为04

如果这是一个基本问题,很抱歉,但我尝试过cut和grep的变体,但找不到解决方案


非常感谢您的帮助。

您可以使用
printf
awk
使用此搜索功能:

srch() {
    printf "%s\n" "${array[@]}" | awk -v s="$1" 'substr($1, 1, 2) == s{
    print substr($1, 3)}' ;
}
然后将其用作:

srch 75
01

srch 73
02

srch 84
03

srch 99
04

您可以使用
printf
awk
使用此搜索功能:

srch() {
    printf "%s\n" "${array[@]}" | awk -v s="$1" 'substr($1, 1, 2) == s{
    print substr($1, 3)}' ;
}
然后将其用作:

srch 75
01

srch 73
02

srch 84
03

srch 99
04

由于bash数组是稀疏的,即使在没有关联数组(将任意字符串映射为键)的较旧版本的bash中,也可以有一个常规数组,该数组只包含要映射的数字索引的键。考虑下面的代码,它占用您的输入数组并生成该形式的输出数组:

array=( 7501 7302 8403 9904 )

replacements=( )                    # create an empty array to map source to dest
for arg in "${array[@]}"; do        # for each entry in our array...
  replacements[${arg:0:2}]=${arg:2} # map the first two characters to the remainder.
done
这将创建一个数组,如下所示(如果在上述代码之后运行
declare-p replacements
,以转储
replacements
变量的描述):

然后,您可以轻松地将其中的任何条目作为不需要外部命令的常量时间操作进行查找:

$ echo "${replacements[73]}"
02
…或独立地迭代键和相关值:

for key in "${!replacements[@]}"; do
  value=${replacements[$key]}
  echo "Key $key has value $value"
done
…将发出:

键73的值为02
键75的值为01
键84的值为03
键99的值为04

注释/参考:

  • 请参阅以了解用于分割元素的语法(
    ${arg:0:2}
    ${arg:2}
  • 有关上述语法的更多详细信息,请参阅或

由于bash数组是稀疏的,即使在没有关联数组(将任意字符串映射为键)的较旧版本的bash中,您也可以有一个常规数组,其中只包含要映射的数字索引的键。考虑下面的代码,它占用您的输入数组并生成该形式的输出数组:

array=( 7501 7302 8403 9904 )

replacements=( )                    # create an empty array to map source to dest
for arg in "${array[@]}"; do        # for each entry in our array...
  replacements[${arg:0:2}]=${arg:2} # map the first two characters to the remainder.
done
这将创建一个数组,如下所示(如果在上述代码之后运行
declare-p replacements
,以转储
replacements
变量的描述):

然后,您可以轻松地将其中的任何条目作为不需要外部命令的常量时间操作进行查找:

$ echo "${replacements[73]}"
02
…或独立地迭代键和相关值:

for key in "${!replacements[@]}"; do
  value=${replacements[$key]}
  echo "Key $key has value $value"
done
…将发出:

键73的值为02
键75的值为01
键84的值为03
键99的值为04

注释/参考:

  • 请参阅以了解用于分割元素的语法(
    ${arg:0:2}
    ${arg:2}
  • 有关上述语法的更多详细信息,请参阅或

很好的解决方案,问题:如果有重复的条目(例如,[73]x2),会发生什么?@l'l,后者会覆盖前者。我看不出问题中有任何特定的行为会与.Hmm冲突。我认为正确的行为取决于OP想要什么——按照我阅读基于
awk
的答案的方式,如果你有一个重复的条目,它会打印两个匹配条目的后缀。如果需要,可以将此扩展为类似的方式(或将
awk
答案扩展为仅使用第一个或最后一个匹配),但可能值得获得明确的规范。很好的解决方案,问题:如果有重复条目(例如,[73]x2),会发生什么?@l'l,后者会覆盖前者。我看不出问题中有任何特定的行为会与.Hmm冲突。我认为正确的行为取决于OP想要什么——按照我阅读基于
awk
的答案的方式,如果你有一个重复的条目,它会打印两个匹配条目的后缀。如果需要的话,可以将其扩展为类似的方式(或者将
awk
答案扩展为仅使用第一个或最后一个匹配),但可能值得获得一个明确的spec.Hmm。如果它真的只是两个数字键,你是对的,我们不能有太长的输入,以至于O(1)和O(n)之间的差异在实践中是那么大;可能会停留在启动和子壳/管道成本是主要驱动因素的领域。OTOH,如果这个查找是在一个紧密的循环中完成的(即每行输入一个),那么我们就可以找到一个调用可以相加的地方,只需要从前面提到的常数因子费用中进行计算。@CharlesDuffy:1e+37次迭代(awk:r:0.573s,u:0.276s,s:0.253s)vs(map:r:0.215s,u:0.104s,s:0.079s)感谢这个基准测试。如果我在函数体中运行
printf“%s\n”${array[@]}>tempFIle.tmp
,然后只保留
awk-v s=“$1”substr($1,1,2)==s{print substr($1,3)}tempFIle.tmp
。@l'l'l,我可以询问该测试的实现细节吗?我想重现-,我发现((I=0;i@CharlesDuffy对不起,我离开了几分钟。你必须考虑我跑的测试是在克莱XE6上,所以它非常快。我缩短了循环,因为你可能不在克雷:我想在正常设置下,你会看到map方法和awk在实际所需时间上的巨大差异。嗯,如果它真的只是两个数字键,你是对的,我们的输入不能太长,以至于O(1)和O(n)之间的差异在实践中是如此之大;可能会停留在启动和子shell/管道成本是主要驱动因素的领域。OTOH,如果这种查找是在一个紧密的循环中完成的(即每行输入一个),然后我们就可以到达一个调用可以累加的地方,只需使用前面提到的常数因子费用。@CharlesDuffy:1e+37次迭代(awk:r:0.573s,u:0.276s,s:0.253s)vs(map:r:0.215s,u:0.104s,s:0.079s)感谢这个基准测试。如果运行
printf“%s\n”“${array[@},上述函数将变得更快>tempFIle.tmp
然后只保留
awk-v s=“$1”substr($1,1,2)==s{print substr($1,3)}'t