如何解决以特定方式格式化文本文件
1|ROW1|IDA|IDB|Z|OP
2|ROW2|IDA|IDC|IDF|IDG|Z|OP
3|ROW3|IDA|IDC|IDF|Z|OP
我想通过像这样展平 ID
列来格式化它:
1|ROW1|IDA|Z|OP
1|ROW1|IDB|Z|OP
2|ROW2|IDA|Z|OP
2|ROW2|IDC|Z|OP
2|ROW2|IDF|Z|OP
2|ROW2|IDG|Z|OP
3|ROW3|IDA|Z|OP
3|ROW3|IDC|Z|OP
3|ROW3|IDF|Z|OP
在脚本中是否有任何简单的方法可以做到这一点?还是我需要编写一个小程序来读取每一行并通过正则表达式匹配一行的每一列?
谢谢你的建议
解决方法
如果你愿意考虑awk,你可以这样做:
awk -F'|' '{
last = 2
for(i = 3; i <= NF; ++i) {
if($i~/^ID/) last = i;
else break;
}
for(i = 3; i <= last; ++i) {
printf("%s|%s|%s",$1,$2,$i);
for(j = last + 1; j <= NF; ++j) {
printf("|%s",$j);
}
printf("\n");
}
}'
对于字段由 |
(-F'|'
参数)分隔的每一行,这是这样做的:
- 第一个循环查找以
ID
(/^ID/
部分)开头的最后一个字段。 - 下一个循环遍历
ID
字段并打印字段 1 和 2,然后是当前的ID
字段。 - 内部循环打印
ID
字段之后的所有字段。
一个可能更易于阅读和维护的版本:
awk -F'|' '{
last = 2;
for(i = 3; i <= NF; ++i) {
if($i~/^ID/) last = i;
else break;
}
last_fields = ""
for(i = last + 1; i <= NF; ++i) {
last_fields = last_fields "|" $i;
}
for(i = 3; i <= last; ++i) {
printf("%s|%s|%s%s\n",$i,last_fields);
}
}'
- 第一个循环查找以
ID
开头的最后一个字段。 - 第二个循环从最后一个
last_fields
字段之后的字段中构建一个变量 (ID
) - 第三个循环打印字段 1、2、当前
ID
字段,然后是last_fields
。
我会在这里使用带有 csv
模块的 Python 脚本:
with open('input.txt') as fdin,open('output.txt','w',newline='') as fdout:
rd = csv.reader(fdin,delimiter='|')
wr = csv.writer(fdout,delimiter='|')
for row in rd:
for item in row[2:-2]:
_ = wr.writerow(row[:2] + [item] + row[-2:])
,
这是一个使用正则表达式的 Notepad++ 解决方案。在 Notepad++ 7.9.1 上测试。
查找:^(.*?\|)(ID\w\|)((?:ID\w\|)+)(.*)$
。
替换为:\1\2\4\r\n\1\3\4
。
选择正则表达式和环绕,不要选择点匹配换行。
反复进行全部替换,直到不再进行替换。所需的全部替换命令的数量将比行中 IDx 字符串的最大数量少 1。
查找字符串的说明:
^(.*?\|) Group 1: Matches leading characters on the line
(ID\w\|) Group 2: Matches the first IDx and its following |
( Group 3 starts
(?:ID\w\|)+ Matches all remaining IDx's and their following |,this is a non-capturing group
) Group 3 ends
(.*)$ Group 4: Everything on line after the last IDx and |
替换字符串输出两行。第一个具有包含第一个 IDx(组 2)的开始(组 1)和结束(组 4)文本。第二行包含围绕其他 IDx 字符串(第 3 组)的开始和结束文本。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。