我有这样的映射文件,如下所示:
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的旧映射和新映射之间的区别。我怎么能在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
答案 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>
选项-1
-2
-3
正在删除相应的列,因此-23
只能保留在第一列。
如果必须经常调用此操作,则启动许多进程可能很长,在这种情况下,只能使用bash builtin和函数来完成:
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[@]}"