найти разницу между старым и новым отображением для каждого clientId - PullRequest
0 голосов
/ 02 мая 2018

У меня есть файл сопоставлений, как показано ниже:

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 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.

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 1 имеет 343, 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. Как я могу сделать это в сценарии оболочки? Это возможно сделать?

Кроме того, если нет никакой разницы, просто создайте пустой массив и зарегистрируйте сообщение.

Обновление:

Для 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 голосов
/ 03 мая 2018

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)
0 голосов
/ 02 мая 2018

стандартных команд

короткое решение с использованием стандартной команды 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 берет два файла (которые должны быть отсортированы лексикографически) и производит вывод с 3 столбцами с разделителем <tab>

  • первый столбец "только в первом файле"
  • второй столбец «только во втором файле»
  • третий столбец "оба"

options -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[@]}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...