解析两个映射文件并提取特定clientId

时间:2018-04-13 22:45:07

标签: linux bash shell awk sed

我有两个这样的映射文件,如下所示:

primary_mapping.txt

{1=[343, 0, 686, 1372, 882, 196], 2=[687, 1, 1373, 883, 197, 736, 1030, 1569], 3=[1374, 2, 884, 737, 198, 1570], 4=[1375, 1032, 1424, 3, 885, 1228], 5=[1033, 1425, 4, 200, 886]}

secondary_mapping.txt

{1=[1152, 816, 1488, 336, 1008], 2=[1153, 0, 817, 337, 1489, 1009, 1297], 3=[1, 1154, 1490, 338], 4=[1155, 2, 339, 1491, 819, 1299, 1635], 5=[820, 1492, 340, 3, 1156]}

在上面的映射文件中,每个clientId都有主映射和辅助映射。例如:clientId 1具有343, 0, 686, 1372, 882, 196主映射和1152, 816, 1488, 336, 1008辅助映射。同样适用于其他clientIds

现在在我的shell脚本中,我想打印PRIMARY_MAPPINGSECONDARY_MAPPING,但仅用于从命令行传递到shell脚本的clientId。例如:在下面的示例中,我传递了1,因此它应该打印出clientId 1的所有主映射和辅助映射。同样地,如果我们传递2,那么它也应该为2做。

./print_mapping.sh 1

下面是我的shell脚本,但我不确定如何解析这两个文件并提取特定clientId的映射:

# extract individual mappings from each of those two files given a particular clientId and assign it to `PRIMARY_MAPPING` and `SECONDARY_MAPPING` array.

for pm in "${PRIMARY_MAPPING[@]}"
do
echo $pm
done

for sm in "${SECONDARY_MAPPING[@]}"
do
echo $sm
done

1 个答案:

答案 0 :(得分:1)

#/bin/bash
for n in {1..5}
do
  echo "$n:"
  for f in primary-mappings.txt secondary-mappings.txt
  do
    sed -r "s/.*\b$n=\[([^]\]+).*/\1/" $f
  done
echo
done

1:
343, 0, 686, 1372, 882, 196
1152, 816, 1488, 336, 1008

2:
687, 1, 1373, 883, 197, 736, 1030, 1569
1153, 0, 817, 337, 1489, 1009, 1297

3:
1374, 2, 884, 737, 198, 1570
1, 1154, 1490, 338

4:
1375, 1032, 1424, 3, 885, 1228
1155, 2, 339, 1491, 819, 1299, 1635

5:
1033, 1425, 4, 200, 886
820, 1492, 340, 3, 1156

for f in primary-mappings.txt部分,您可以提取循环并将其声明为函数,它将n作为参数n=$1仅输出单个clientID。

赋值给数组

要回答注释中的问题,请将内部值分配给数组。要使用数组,您应该阅读this Bash-FAQ chapter之类的内容。这是一个具体的例子

#!/bin/bash
mapfiles=(primary-mappings.txt secondary-mappings.txt)

declare -a arr

mappingsByClientID () {
  id=$1 # 1 to 5 
  file=${mapfiles[$2]} # 0 to 1
  arr=($(sed -r "s/.*\b${id}=\[([^]\]+).*/\1/; s/,/ /g" $file))
  echo "${arr[@]}"
}

# assign output of function to an array
pri3=($(mappingsByClientID 3 0))
snd4=($(mappingsByClientID 4 1))

解释

不要忘记使用shebang。将文件名存储在数组中:

#!/bin/bash
mapfiles=(primary-mappings.txt secondary-mappings.txt)

定义一个函数,它需要ID和 - 对于主要或次要0或1:

mappingsByClientID () {
  id=$1 # 1 to 5 
  file=${mapfiles[$2]} # 0 to 1
  arr=($(sed -r "s/.*\b${id}=\[([^]\]+).*/\1/; s/,/ /g" $file))
  echo "${arr[@]}"
}

sed-line不仅从2=[687, 1, 1373, 883, 197, 736, 1030, 1569]中选取部分,并将其缩小为值,用逗号分隔,但删除逗号,因为这就是bash喜欢的数组赋值看起来像a=(x y z)

用法:

# Testing
# assign output of function to an array
pri3=($(mappingsByClientID 3 0))
snd4=($(mappingsByClientID 4 1))
# access whole array
echo "whole arr pri 3: ${pri3[@]}"
echo "whole arr snd 4: ${snd4[@]}"
# access by literal index (starting at 0)
echo "first el. in arr pri 3: ${pri3[0]}"
# arraylength with #, index of last is ((len-1)):
len2nd=$((${#snd4[@]}-1))
# access by array index 
echo "last  el. in arr snd 4: ${snd4[$len2nd]}"

当然,使用类似C语言的3dim数组会很方便:

# doesn't work, 3Dim-Arrays
for n in {1..5}
do
  for i in 0 1
  do
    # doesn't work:
    # arr[$n][$i]=($(mappingsByClientID $n $i))
    # doesn't work either
    # arr${n}${i}=($(mappingsByClientID $n $i))
  done
done
# echo arr[3][0][2]
# echo arr30[2]

但是没有对此的支持,并且阵列的不同长度使得难以实现一些技巧。