我有一个如下所示的文件:
S123456789^ABC|00||00||ZZ|MW00021C|ZZ|207RI0200X~LX|1~SV2|6666|FG>FG997|879.5|UN|4~DTP|472|D8|20150213~REF|6R|JHYU0003707988-1~LIN||N4|67202004164~LX|2~SV2|1234|FG>BP990|879.5|UN|12~DTP|472|D8|20170413~REF|6R|ABCD0003707988-1~LIN||N4|67202004908~
我想提取1
下一个LX
,下FG997
一个,然后再提取到LIN||N4 旁边的 67202004164,然后再次提取到下一个,同样如下。SV2|****|HC> ,879.5
4
UN,20150213
DTP|472|D8
2
LX
有人可以帮助我使用 UNIX 实现这一目标吗?
我有很多大文件需要以这种方式解析。
答案1
如果文件的所有行都具有相同的结构,则可以像下面一样使用 awk。
$ awk -F"[|^~>]" -v OFS="," '{for (i=1;i<=NF;i++) print "Field",i,"---value:",$i}' <<<"$a"
#Output will be like:
Field,1,---value:,S123456789
Field,2,---value:,ABC
Field,3,---value:,00
Field,4,---value:,
Field,5,---value:,00
Field,6,---value:,
Field,7,---value:,ZZ
Field,8,---value:,MW00021C
Field,9,---value:,ZZ
Field,10,---value:,207RI0200X
Field,11,---value:,LX
Field,12,---value:,1
Field,13,---value:,SV2
Field,14,---value:,6666
Field,15,---value:,FG
Field,16,---value:,FG997
##More fields here - goes up to 51 ##
awk-F
定义分隔符(输入字段分隔符),并且可以是多个字符。
在上面的示例中,我使用 chars |
, ^
, ~
,>
作为分隔符来强制 awk 将行分割成更多部分。
您可以添加更多分隔符来强制 awk 将字段分割成更多部分。
PS:我的示例中的变量 $a 包含您问题的文本。
由于您确定了所需的字段,因此您可以构建如下所示的脚本来打印所需的字段:
$ awk -F"[|^~>]" -v OFS="," '{print $1,$12,$16,etc}' <<<"$a"
OFS 定义 print 将用于打印字段的输出分隔符。
关于 awk 中的打印,请注意:
* 当我们打印类似'{print $1,$2}'
这样的内容时,这两个字段由 OFS 分隔(上例中为逗号) --> field1,field2
* 当我们打印类似'{print $1 $2}'
awk 的内容时,会打印两个字段连接起来 - 一个接一个,不分隔之间 -->field1field2
答案2
这种事情轻而易举Perl
。
perl -lne '
BEGIN{ $SKIP = qr/(?:[^|]+[|])/; $, = ","; }
print map { s/[~].*[|]/,/; y/|/,/; s/,?$//r; }
/
^[^^]+
| (?: LX [|] ) \K \d+
| (?: SV2 [|] \d+ [|] FG[>] )\K $SKIP{2}
| (?: UN [|] ) \K \d+ $SKIP{3} \d+
| (?: LIN [|][|] $SKIP ) \K \d+
/xg;
' yourfile
解释:
-l
=> ORS=FS=\n
-n
=> dont print unless asked to
-e
=> 接下来是Perl
代码。$,
=>OFS
BEGIN
block 定义了一个正则表达式,它跳过一个管道分隔的字段。我们can
(读为box
而不是ability
)这个正则表达式是因为当我们必须跳过 2 个管道分隔字段(有时甚至是 3 个)时,它会多次出现。这使得看起来regex
不那么可怕。
/.../xg 返回所有匹配列表(仅那些出现在 \K 右侧的列表),然后 map { ... } 进行一些处理并将结果打印到标准输出。
输出
S123456789,1,FG997,879.5,4,20150213,67202004164,2,BP990,879.5,12,20170413,67202004908