文件求交拼接方式

本文介绍了一种使用Shell和Python实现的多文件求交并拼接的方法,适用于处理包含百万级别的数据行。通过先将文件数据按唯一键聚合排序,再利用Python程序逐行读取并比较数据,实现数据的高效合并。

python 方式求交拼接

使用于两个以上的小文件求交,并进行拼接 原理将各个文件以单独的对象存储,然后以key当作对应对象中的key,然后按照某个文件进行逐个对象拼接即可

#!/bin/env python
# filename: merge_data_by_dict.py

fid_a = open('a.txt')
fid_b = open('b.txt')
fid_c = open('c.txt','w')
lines_a = fid_a.readlines()
lines_b = fid_b.readlines()
lines_c = []
for i in range(0,len(lines_b)):
    lines_a[i]= lines_a[i].strip('\n\r')
    lines_c.append(lines_a[i]+lines_b[i])
    fid_c.writelines(lines_c[i])
复制代码

shell + python 方式求交拼接(方案一)

假定文件格式:

  1. 唯一字符串 \t 字段值1-1
  2. 唯一字符串 \t 字段值2-1 \t 字段值2-2

假定文件不是特别大,且本地可以运行,文件行数假定百万级别

  1. 考虑将两个文件中的数据,按照唯一字符串聚合后,按照文件先后顺序进行排列
  2. 处理文件中的原始数据,为数据增加一列数据,该列数据值代表所属文件,且为数字即可
  3. 同时输出两份文件内容,并将文件按照指定列排序(聚合key、文件索引均需放到对应的列中),然后按照内容进行排序
  4. 准备一个python程序,逐行读取数据,并用下一行数据与上一行数据进行对比,看是否key相同,相同则将两份数据merge,不同则跳过或输出当前行信息
步骤一:
file_index=0
cat ${file_path} \
    | awk -F'\t' \
        -v index="${file_index}" \
    '{
        other_str = "";
        for(i=2; i<=NF; i++) {
            other_str = other_str"\t"$i;
        }
        print $1"\t"index""other_str;
    }' > ${file_path}.${file_index}
复制代码

步骤二:

cat file.1 file.2 | sort -k1 -k2 > file.tmp
复制代码

步骤三:

#!/bin/env python
# filename: merge_data.py

import sys

last_list = []
def main():
    """
    主执行函数
    """
    global last_list
    
    file0_empty_data = ['0', '0', '0']
    file1_empty_data = ['0', '0', '0', '0']
    
    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue
        
        llist = line.split('\t')
        if len(llist) not in [3, 4]:
            continue
        
        if not last_list:
            if llist[1] == '0':
                last_list = llist
            else:
                ret_list = file0_empty_data + llist
                print "%s" % '\t'.join(tuple(ret_list)
        else:
            if llist[1] == '0':
                ret_list  = last_list + file1_empty_data
                print "%s" % '\t'.join(tuple(ret_list)
                last_list = llist
            else:
                if llist[0] == last_list[0]:
                    ret_list = last_list + llist
                    print "%s" % '\t'.join(tuple(ret_list)
                    last_list = []
                else:
                    ret_list  = last_list + file1_empty_data
                    print "%s" % '\t'.join(tuple(ret_list)
    
    if last_list:
        ret_list  = last_list + file1_empty_data
        print "%s" % '\t'.join(tuple(ret_list)
        last_list = llist

if __name__ == '__main__':
    main()
复制代码

步骤四:

cat file.tmp | python merge_data.py
复制代码

shell + python 方式求交拼接(方案二)

  1. 针对数据文件较大,无法直接操作两个文件时,可以参考该种方式
  2. 将文件按照指定key,进行hash计算,然后按照多个文件的方式进行hash输出到每个小文件中
  3. 然后每个小文件按照上述两种方案之一进行操作即可

假定文件格式

  1. 唯一字符串 \t 字段值1-1
  2. 唯一字符串 \t 字段值2-1 \t 字段值2-2
#!/bin/bash

file_nums=100
file_index=0

# 拆文件为各个小文件
cat file.1 | awk -F'\t' \
-v file_pos="${file_index}" \
-v file_nums="${file_nums}" \
'{
    file_index = $1 % file_nums;
    file_path  = "file_data."file_index;
    print file_pos"\t"$0 >> file_path;
}'

function merge_data() {
    local file_path=$1
    cat ${file_path} 2>/dev/null \
        | sort -k2 -k1 \
        | python merge_data.py
}

# 遍历小文件进行求交拼接操作
for(( i=0; i<=$file_nums; i++ ));do
    tmp_file_path="file_data."$i
    merge_data "${tmp_file_path}"
done
复制代码

转载于:https://juejin.im/post/5bc8b28fe51d450e6749bd88

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值