找出每个clientId的旧映射和新映射之间的差异

时间:2018-05-02 04:51:33

标签: python linux bash shell sed

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

new_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]}

new_secondary_mapping.txt

{1=[1152, 816, 1488, 336, 1008], 2=[1153, 0, 817, 337, 1489, 1009, 1297], 3=[1, 1154, 1490, 338]}

在上面的映射文件中,每个clientId都有新的主要和新的辅助映射。例如:clientId 1343, 0, 686, 1372, 882, 196个新的主映射和1152, 816, 1488, 336, 1008个新的辅助映射。同样对于其他clientIds也是如此。下面是我的脚本,它为每个clientId打印数组:

#!/bin/bash
mapfiles=(new_primary_mapping.txt new_secondary_mapping.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
# and get mapping for clientId 3
pri=($(mappingsByClientID 3 0))
snd=($(mappingsByClientID 3 1))

# print whole array
echo "whole arr pri: ${pri[@]}"
echo "whole arr snd: ${snd[@]}"

现在我有两个其他文件,如下所示,它们具有相同clientId's的旧映射。

old_primary_mapping.txt

{1=[686, 1372, 882, 196], 2=[883, 197, 736, 1030, 1569], 3=[1374, 2, 884, 737]}

old_secondary_mapping.txt

{1=[1488, 336, 1008], 2=[817, 337, 1489, 1009, 1297], 3=[1490, 338]}

问题陈述

现在我需要阅读所有四个文件,并且对于每个clientId,我需要弄清楚新旧映射之间的不常见(意义不同)。

例如:clientId 1343, 0, 686, 1372, 882, 196个新的主映射和1152, 816, 1488, 336, 1008个新的辅助映射。 此外,clientId 1还有686, 1372, 882, 196旧的主映射和1488, 336, 1008旧的辅助映射。

所以我将创建一个pri数组,它将包含此条目:343 0和sec数组,它将包含此条目:1152 816。因为这些是每个clientId的旧映射和新映射之间的区别。我怎么能在shell脚本中这样做?这可能吗?

如果没有区别,那么只需创建一个空数组并记录一条消息。

更新

对于clientId 1,它应该打印:

pri=(343 0)
snd=(1152 816)

clientId 2

pri=(687 1 1373)
snd=(1153 0)

clientId 3

pri=(198 1570)
snd=(1 1154)

注意:只要数字相同,那么它就是匹配。数字排序无关紧要。所以我需要找到每个clientId不常见的数字。

这是我删除文件的方式,但是当我运行它时,它会给我错误:

for dir_name, numbers in (('primary', pri), ('secondary', snd)):
    for number in numbers:
        for filename in glob.glob('/{}/proc_{}_for_*.log'.format(dir_name, number)):
             os.unlink(filename)

这是我得到的错误:

NameError: name 'pri' is not defined

2 个答案:

答案 0 :(得分:1)

Python 解决方案:

diff_mappings.py脚本:

import sys, re, json

with open(sys.argv[1]) as old_primary, open(sys.argv[2]) as new_primary, \
    open(sys.argv[3]) as old_second, open(sys.argv[4]) as new_second:

    prepare_json = lambda f: json.loads(re.sub(r'([0-9]+)=', '"\\1":', f.read())) 
    old_pr_data = prepare_json(old_primary)
    new_pr_data = prepare_json(new_primary)
    old_snd_data = prepare_json(old_second)
    new_snd_data = prepare_json(new_second)

    for k in sorted(old_pr_data):
        print('ClientId ' + k)
        print('pri=({})'.format(' '.join(map(str, set(old_pr_data[k]) ^ set(new_pr_data[k])))))
        print('snd=({})\n'.format(' '.join(map(str, set(old_snd_data[k]) ^ set(new_snd_data[k])))))

用法(输入文件的顺序很重要,但也可以重新排列方法以直接在脚本中按名称访问文件):

python diff_mappings.py old_primary_mapping.txt new_primary_mapping.txt old_secondary_mapping.txt new_secondary_mapping.txt

输出:

ClientId 1
pri=(0 343)
snd=(1152 816)

ClientId 2
pri=(1 687 1373)
snd=(0 1153)

ClientId 3
pri=(198 1570)
snd=(1 1154)

答案 1 :(得分:0)

标准命令

使用标准unix命令sort和comm

的简短解决方案
new_primary=(343 0 686 1372 882 196)
old_primary=(686 1372 882 196)
comm -23 <( printf "%s\n" "${new_primary[@]}" | sort ) <( printf "%s\n" "${old_primary[@]}" | sort )

comm需要两个文件(必须按字典顺序排序)并使用分隔符<tab>

生成包含3列的输出
  • 第一栏“仅在第一档”
  • 第二栏“仅在第二档”
  • 第三栏“两个”

选项-1 -2 -3正在删除相应的列,因此-23只能保留在第一列。

如果必须经常调用此操作,则启动许多进程可能很长,在这种情况下,只能使用bash builtin和函数来完成:

bash 4

arr_to_set() {
    declare -n arr_name=$1
    local set_name=$2 e
    declare -gA "$set_name=()"
    for e in "${arr_name[@]}"; do
        declare -g $set_name[$e]=1
    done
}

comm_set() {
    declare -n set1_=$1 set2_=$2
    declare -gA "comm_only1=()" "comm_only2=()" "comm_both=()"
    for k in "${!set1_[@]}"; do
        if [[ -z ${set2_[$k]} ]]; then
            comm_only1[$k]=1
        else
            comm_both[$k]=1
        fi
    done
    for k in "${!set2_[@]}"; do
        if [[ -z ${set1_[$k]} ]]; then
            comm_only2[$k]=1
        fi
    done
}

new_primary=(343 0 686 1372 882 196)
old_primary=(686 1372 882 196)
arr_to_set new_primary new_primary_set
arr_to_set old_primary old_primary_set
comm_set new_primary_set old_primary_set
typeset -p comm_only1
printf "%8s\n" "${!comm_only1[@]}"