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

2024-10-03 13:19:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我有如下映射文件:

新建\u主_映射.txt

{1=[343, 0, 686, 1372, 882, 196], 2=[687, 1, 1373, 883, 197, 736, 1030, 1569], 3=[1374, 2, 884, 737, 198, 1570]}

新建_映射.txt

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

在上面的映射文件中,每个clientId都有新的主映射和新的次映射。例如:clientId 1具有343, 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的旧映射。你知道吗

旧\u小学_映射.txt

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

旧的_映射.txt

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

问题陈述

现在,我需要读取所有四个文件,对于每个clientId,我需要找出新映射和旧映射之间的不常见之处(意思不同)。你知道吗

例如:clientId 1具有343, 0, 686, 1372, 882, 196新的主映射和1152, 816, 1488, 336, 1008新的次映射。 而且clientId 1686, 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)

注:只要数字是相同的,那就是匹配。数字的顺序无关紧要。因此,我需要找到那些不是每个客户的共同数字。你知道吗

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

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

Tags: 文件tonameechotxtfor数字数组
2条回答

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)

标准命令

使用标准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内置函数和函数执行此操作:

重击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[@]}"

相关问题 更多 >