如何用Awk仅转置特定行至多列?附具体数据转置需求
使用Awk仅将特定行转置为多列的方法
通用思路
要实现仅对特定行进行转置,核心分为两步:
- 锁定目标行:通过行号、关键字等条件筛选出需要处理的行(比如包含
invStatus:的行)。 - 行内内容重组:对目标行的内容拆分、重构,把单行里的元素转换为多行(或按需调整为多列)。
针对你给出的具体输入的解决方案
你的输入是一长串包含多组键值对的文本,从你给出的输出示例来看,应该是希望保留invBase:及之后的内容为一行,同时将前面的键值对转置为每行一个。下面提供两种常见需求的实现:
需求1:将前面的键值对转置为多行,保留invBase:及后续内容为一行
假设输入文件名为input.txt,可以用以下Awk脚本处理:
/invStatus:/ { # 匹配包含目标关键字的行 # 拆分出invBase前后的两部分内容 split($0, parts, /invBase:/) front_content = parts[1] back_content = "invBase:" parts[2] # 处理前面的键值对,转置为单行 while (match(front_content, /([A-Za-z0-9_]+: [^A-Za-z0-9_]+)/)) { print substr(front_content, RSTART, RLENGTH) front_content = substr(front_content, RSTART + RLENGTH + 1) } # 单独处理带多值的invState键 if (match(front_content, /invState: .+/)) { print substr(front_content, RSTART) } # 输出invBase及之后的完整内容 print back_content }
执行命令:awk -f transpose.awk input.txt,输出结果如下:
invStatus: ONLINE System: 55 StatFail: 0 invState: 0 Unknown invFailReason: None invBase: SYS-MG5-L359-XO1-TRAFFIC STAT 5: TRAF2 invFlag: 0xeee5 SEMAN PRESENT STATUS H_DOWN BASE LOGIC_ONLINE DEX EPASUS INDEX ACK dexIn: 0 dexIO: 0 badTrans: 0 badSys: 0 io_IN: 0 io_OUT: 0 Tr_in: 0 Tr_out: 0
需求2:仅提取invBase:及之后的内容
如果你的实际需求只是去掉前面的键值对,直接保留invBase:开始的部分,命令会更简洁:
/invStatus:/ { sub(/^.*invBase:/, "invBase:") print $0 }
执行后直接得到你想要的示例输出:
invBase: SYS-MG5-L359-XO1-TRAFFIC STAT 5: TRAF2 invFlag: 0xeee5 SEMAN PRESENT STATUS H_DOWN BASE LOGIC_ONLINE DEX EPASUS INDEX ACK dexIn: 0 dexIO: 0 badTrans: 0 badSys: 0 io_IN: 0 io_OUT: 0 Tr_in: 0 Tr_out: 0
关键知识点说明
- 筛选特定行:用
/关键字/可以快速匹配包含目标内容的行,也可以用NR==行号指定具体行位置。 - 字符串处理:
split()按分隔符拆分字符串,sub()用于替换匹配的内容,match()结合正则能精准定位键值对的边界。 - 正则适配:针对带空格的键值(比如
invState: 0 Unknown),需要调整正则规则避免拆分错误。
内容的提问来源于stack exchange,提问作者ya801
相关产品推荐
相关产品推荐

