You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下以指定字段为唯一键实现垂直数据转水平过滤

问题描述

需要处理以<SUBBEGIN>和<SUBEND>包裹的订阅数据,提取指定字段并转换为指定的水平格式。

原始输入数据

<SUBBEGIN
SUBSCRIBERIDENTIFIER=803838478;
PAIDTYPE=0;
SUBSCRIPTION=TOOMUCH&73337E0380B4B30F&1&AAA&BBB&CCC&1&1&FFFFFFFFFFFFFFFF&255&1&255&256&FFFFFFFFFFFFFFFF&0&0&128&1&255&255&FFFFFFFFFFFFFF&FFFFFFFFFFFFFF&0&0&0&1&0&0&1;
SUBSCRIPTION=TASKS&E7CC601262AB3535&1&DDD&EEE&FFF&2&1&FFFFFFFFFFFFFFFF&255&0&255&256&FFFFFFFFFFFFFFFF&0&0&128&1&255&255&FFFFFFFFFFFFFF&FFFFFFFFFFFFFF&0&21&0&1&0&0&1;
<SUBEND
<SUBBEGIN
SUBSCRIBERIDENTIFIER=705959905;
PAIDTYPE=254;
SUBSCRIPTION=REALLY&73337E0380B4B30F&1&GGG&HHH&LLL&1&1&FFFFFFFFFFFFFFFF&255&1&255&256&FFFFFFFFFFFFFFFF&0&0&128&1&255&255&FFFFFFFFFFFFFF&FFFFFFFFFFFFFF&0&0&0&1&0&0&1;
SUBSCRIPTION=TIRED&E7CC601262AB3535&1&MMM&NNN&PPP&2&1&FFFFFFFFFFFFFFFF&255&0&255&256&FFFFFFFFFFFFFFFF&0&0&128&1&255&255&FFFFFFFFFFFFFF&FFFFFFFFFFFFFF&0&21&0&1&0&0&1;
<SUBEND    

预期表头

SUBSCRIBERIDENTIFIER,,,PAIDTYPE,,1,255,SERVICENAME,SUBSCRIBEDATETIME,VALIDFROMDATETIME,EXPIREDDATETIME,,,,,

字段提取规则

  • SUBSCRIBERIDENTIFIER:取自对应字段的数值(如803838478)
  • PAIDTYPE:取自对应字段的数值(如0)
  • SERVICENAME:取自SUBSCRIPTION字段的第一个&前的内容(如TOOMUCH)
  • SUBSCRIBEDATETIME:SUBSCRIPTION字段的第4个分隔值(如AAA)
  • VALIDFROMDATETIME:SUBSCRIPTION字段的第5个分隔值(如BBB)
  • EXPIREDDATETIME:SUBSCRIPTION字段的第6个分隔值(如CCC)
  • 固定填充字段:,,1,255,和末尾的,,,,,

尝试的脚本及错误输出

使用以下awk脚本:

awk -F"&" '/^<SUBBEGIN$/{a=1} a && /^[[:blank:]]+(SUBSCRIBERIDENTIFIER|PAIDTYPE|SUBSCRIPTION)/{l=l OFS $1} a && /^<SUBEND$/ {print l; a=l=""}' sample.txt

得到的错误输出:

SUBSCRIBERIDENTIFIER=803838478;         PAIDTYPE=0;         SUBSCRIPTION=TOOMUCH         SUBSCRIPTION=TASKS
SUBSCRIBERIDENTIFIER=705959905;         PAIDTYPE=254;         SUBSCRIPTION=REALLY         SUBSCRIPTION=TIRED
解决方案

使用以下awk脚本可以实现需求:

awk '
/SUBBEGIN/ { in_block=1; next }
/SUBEND/ { in_block=0; next }
in_block {
    if ($0 ~ /SUBSCRIBERIDENTIFIER=/) {
        sub(/;$/, "", $0);
        split($0, arr, "=");
        sub_id = arr[2];
    }
    else if ($0 ~ /PAIDTYPE=/) {
        sub(/;$/, "", $0);
        split($0, arr, "=");
        paid_type = arr[2];
    }
    else if ($0 ~ /SUBSCRIPTION=/) {
        sub(/;$/, "", $0);
        split($0, arr, "=");
        sub_val = arr[2];
        split(sub_val, sub_arr, "&");
        printf "%s,,,%s,,1,255,%s,%s,%s,%s,,,,,\n", 
            sub_id, paid_type, 
            sub_arr[1], sub_arr[4], sub_arr[5], sub_arr[6];
    }
}
' sample.txt

脚本逻辑说明

  1. 标记数据块:遇到SUBBEGIN时开启数据块标记in_block=1,遇到SUBEND时关闭标记。
  2. 提取固定字段:
    • 处理SUBSCRIBERIDENTIFIER行:去掉末尾分号,按=分割获取数值存入sub_id。
    • 处理PAIDTYPE行:同理获取数值存入paid_type。
  3. 处理订阅字段:
    • 去掉SUBSCRIPTION行末尾分号,先按=分割出&分隔的内容。
    • 再按&分割该内容,提取第1、4、5、6个元素作为服务名和时间字段。
  4. 按预期格式拼接所有字段并打印,每个SUBSCRIPTION行对应一行输出。

执行结果

运行脚本后将得到预期输出:

803838478,,,0,,1,255,TOOMUCH,AAA,BBB,CCC,,,,,
803838478,,,0,,1,255,TASKS,DDD,EEE,FFF,,,,,
705959905,,,254,,1,255,REALLY,GGG,HHH,LLL,,,,,
705959905,,,254,,1,255,TIRED,MMM,NNN,PPP,,,,,

内容的提问来源于stack exchange,提问作者rujak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:24:52