awk - AWK 和多个空格(列分隔符)
问题描述
大家,早安,
要使用来自发布者软件的数据,我有可以通过 CLI (Linux Shell) 调用的函数。
其中一个以以下格式将数据返回给我:
2601424 OPTDCBO3 EERP O 0254 5512240 TDCTAC01 B 00 0000000 N N
2602451 WHA EERP O 0254 5512353 03ZEE003 B 00 0000000 N N
2602748 OPTDCBO4 EERP O 0254 5512380 TDCTAC01 B 00 0000000 N N
2603290 OPTDCBO3 EERP O 0254 5512440 TDCTAC01 B 00 0000000 N N
2604594 OPTDCBO3 EERP O 0254 5512560 TDCTAC01 B 00 0000000 N N
2605631 OP49LDB1 TRAN O 0254 EDRZZZ02 B 2605627-EDR 00 0000000 N N
2605657 OP49LDB1 TRAN O 0254 EDRZZZ02 B 2605652-EDR 00 0000000 N N
2605663 OP49LDB1 TRAN O 0254 EDRZZZ02 B 2605653-EDR 00 0000000 N N
2606116 OPTDCBO3 EERP O 0254 5513080 TDCTAC01 B 00 0000000 N N
2716077 OPTDCBO3 EERP O 0255 5610080 TDCTAC01 B 00 0000000 N N
2716564 SOG01 TRAN O 0255 s2716564 TACSOG01 B 2716504-TAC 00 0000000 N N
2718631 OPTDCBO3 EERP O 0255 5610160 TDCTAC01 B 00 0000000 N N
7158273 OPTDCBO4 EERP O 0251 5203300 TDCTAC01 B 00 0000000 N N
7158672 WHA EERP O 0251 5203342 03ZEE001 B 00 0000000 N N
7158939 ZZZA4 LIST O 0251 B 7158938-49W 00 0000000 N N
7158978 OPTDCBO3 EERP O 0251 5203400 TDCTAC01 B 00 0000000 N N
7159853 OPTDCBO4 EERP O 0251 5203540 TDCTAC01 B 00 0000000 N N
2724704 SOU02 TRAN I 0255 s2724704 FTP_B E 2724704-SOU 00 0000000 N N
2724707 PRODS2I EERP O 0255 6219255 S2IRCE03 E 00 0000000 N N
2724708 SOU01 TRAN I 0255 s2724708 FTP_B E 2724708-SOU 00 0000001 N N
2724709 SON01 TRAN O 0255 s2724709 SOUSON11 E 2724708-SOU 00 0000001 N N
在上面的例子中,我试图收集我能遇到的所有案例,但即使不是详尽无遗,我正在寻找的帮助也能让我解决问题:)
我的命令的返回按列显示上述格式的数据,前 5 列用空格分隔,第 5 列和第 6 列用一个或两个空格(视情况而定)分隔。有时第 6 列和第 7 列完全是空的。
目的是能够在正确分隔的文本文件中返回部分或全部这些数据(例如,每个字段之间使用逗号)。
今天,如果我想检索第 1 列和第 7 列,我使用以下命令:
command | awk -F" " '{ print $1,$7 }'
但当然,它给了我这样的结果:
2603290 TDCTAC01
2604594 TDCTAC01
2605631 B
2605657 B
2605663 B
2606116 TDCTAC01
2606214 TDCTAC01
7158672 03ZEE001
7158939 7158938-49W
7158978 TDCTAC01
awk 将填充有空格的列视为多个相邻分隔符,而不是“空”列,因此返回以下非空列的数据。
您是否有一个解决方案,以便在处理有时有两个空格来分隔两列的事实时,将超过 X 个空格的序列视为一个空列?
注意: N°6 列可以由 1 到 6 个数字字符组成,因此不能简单地使用固定宽度来分隔列。
谢谢!
解决方案
wrt Column N°6 can be composed of 1 to 6 numeric characters, so you cannot simply use a fixed width to delimit the column.
- 当然可以。该列的宽度固定为 8 个字符的宽度(或 9 个以懒惰地包含分隔符空间) - 使用它并修剪前导/尾随空格 ( gsub(/^ +| +/,"",$6)
) 以留下您感兴趣的值。
以下是使用 GNU awk for 识别所有字段的方法FIELDWIDTHS
(对于其他 awk,您需要一个while(substr())
循环):
awk -v FIELDWIDTHS="7 9 5 2 5 9 9 2 16 3 8 2 3" '
{
print "----"
print $0
for (i=1;i<=NF;i++) {
gsub(/^ +| +$/,"",$i)
print i, "<" $i ">"
}
}
' file
例如:
$ cat file
2602451 WHA EERP O 0254 5512353 03ZEE003 B 00 0000000 N N
2605657 OP49LDB1 TRAN O 0254 EDRZZZ02 B 2605652-EDR 00 0000000 N N
2724704 SOU02 TRAN I 0255 s2724704 FTP_B E 2724704-SOU 00 0000000 N N
.
$ awk -v FIELDWIDTHS="7 9 5 2 5 9 9 2 16 3 8 2 3" '{ print "----"; print $0; for (i=1;i<=NF;i++) {gsub(/^\s+|\s+$/,"",$i); print i, "<" $i ">"} }' file
----
2602451 WHA EERP O 0254 5512353 03ZEE003 B 00 0000000 N N
1 <2602451>
2 <WHA>
3 <EERP>
4 <O>
5 <0254>
6 <5512353>
7 <03ZEE003>
8 <B>
9 <>
10 <00>
11 <0000000>
12 <N>
13 <N>
----
2605657 OP49LDB1 TRAN O 0254 EDRZZZ02 B 2605652-EDR 00 0000000 N N
1 <2605657>
2 <OP49LDB1>
3 <TRAN>
4 <O>
5 <0254>
6 <>
7 <EDRZZZ02>
8 <B>
9 <2605652-EDR>
10 <00>
11 <0000000>
12 <N>
13 <N>
----
2724704 SOU02 TRAN I 0255 s2724704 FTP_B E 2724704-SOU 00 0000000 N N
1 <2724704>
2 <SOU02>
3 <TRAN>
4 <I>
5 <0255>
6 <s2724704>
7 <FTP_B>
8 <E>
9 <2724704-SOU>
10 <00>
11 <0000000>
12 <N>
13 <N>
推荐阅读
- ruby-on-rails - Rails 5 升级错误 - Bundler 找不到 gem "actionpack" 的兼容版本:
- flutter - 如何解决 ListView.builder 底部溢出问题?
- c++ - 我可以将模板转换/转换为其他模板类型吗?
- python-3.x - 更有效的方法来蛮力寻找 (x+y)^2=str(x)+str(y) 的解决方案?可以矢量化吗?
- css - 无法在 css-grid-animation 中进行渲染延迟?
- c++ - 如何更改鼠标光标的大小?
- html - 为什么我在单击表单字段时会被重定向到禁止页面?
- python - 使用 Pandas 在文件中写入二进制数时遇到问题
- jquery - 当用户单击页面正文的其他位置时隐藏 nabber
- git - Git rebase,压缩两个提交并保持原样