如何从管道分隔文件中归档的数据中删除管道字符

时间:2020-07-17 13:30:50

标签: python linux shell unix

专家,我从源系统得到一个简单的管道定界文件,它具有自由流动的文本字段,对于其中一个记录,我看到“ |”字符作为数据的一部分进入。这不均匀地破坏了我的文件,并且没有被解析为正确的字段数。我要替换“ |”在数据字段中带有“#”。

来自源系统的记录。该文件中共有9个字段。

OutboundManualCall|H|RTYEHLA HTREDFST|Free"flow|Text|20191029|X|X|X|3456

如果您注意到第四个字段-Free“ flow | Text,这是来自其中带有管道的来源的完整值。 我想将其更改为“ Free” flow#Text,然后使用管道定界符读取文件。

期望的结果-

OutboundManualCall|H|RTYEHLA HTREDFST|Free"flow#Text|20191029|X|X|X|3456

我尝试了几种awk / sed组合,但没有得到想要的输出。

谢谢

2 个答案:

答案 0 :(得分:1)

由于您知道有9个字段,而第4个字段是个问题:取前3个字段和后5个字段,剩下的就是第4个字段。

您确实标记了,所以这里有些重击:我确定python等效项已经关闭:

line='OutboundManualCall|H|RTYEHLA HTREDFST|Free"flow|Text|20191029|X|X|X|3456'
IFS='|'

read -ra fields <<<"$line"
first3=( "${fields[@]:0:3}" )
last5=( "${fields[@]: -5}" )

tmp=${line#"${first3[*]}$IFS"}   # remove the first 3 joined with pipe
field4=${tmp%"$IFS${last5[*]}"}  # remove the last 5 joined with pipe
data=( "${first3[@]}" "$field4" "${last5[@]}" )

newline="${first3[*]}$IFS${field4//$IFS/#}$IFS${last5[*]}"
# .......^^^^^^^^^^^^....^^^^^^^^^^^^^^^^^....^^^^^^^^^^^
printf "%s\n" "$line" "$newline"
OutboundManualCall|H|RTYEHLA HTREDFST|Free"flow|Text|20191029|X|X|X|3456
OutboundManualCall|H|RTYEHLA HTREDFST|Free"flow#Text|20191029|X|X|X|3456

使用awk更为简单:如果有10个字段,则将字段4和5合并,然后将其余字段向下移动一个。

echo "$line" | awk '
    BEGIN { FS = OFS = "|" }
    NF == 10 {
        $4 = $4 "#" $5
        for (i=5; i<NF; i++)
            $i = $(i+1)
        NF--
    }
    1
'
OutboundManualCall|H|RTYEHLA HTREDFST|Free"flow#Text|20191029|X|X|X|3456

答案 1 :(得分:0)

您使用Python标记了您的问题,因此我认为基于Python的答案是可以接受的。 我认为并非文件中的所有记录都具有附加的“ |”其中,但只有一些记录具有“ |”在自由文本列中。 举一个更现实的例子,我创建了一个包含一些正确记录和一些错误记录的输入。

我使用StringIO模拟文件,在您的环境中以'open'读取真实文件。

from io import StringIO

sample = 'OutboundManualCall|H|RTYEHLA HTREDFST|Free"flow|Text|20191029|X|X|X|3456\nOutboundManualCall|J|LALALA HTREDFST|FreeHalalText|20191029|X|X|X|3456\nOutboundManualCall|J|LALALA HTREDFST|FrulaalText|20191029|X|X|X|3456\nOutboundManualCall|H|RTYEHLA HTREDFST|Free"flow|Text|20191029|X|X|X|3456'
    
infile = StringIO(sample)
outfile = StringIO()

for line in infile.readlines():
    cols = line.split("|")
    if len(cols) > 9:
        print(f"bad colum {cols[3:5]}")
        line = "|".join(cols[:3]) + "#".join(cols[3:5]) + "|".join(cols[5:])
    outfile.write(line)
print("Corrected file:") 
print(outfile.getvalue())

结果:

> bad colum ['Free"flow', 'Text']
> bad colum ['Free"flow', 'Text']
> Corrected file:
> OutboundManualCall|H|RTYEHLA HTREDFSTFree"flow#Text20191029|X|X|X|3456
> OutboundManualCall|J|LALALA HTREDFST|FreeHalalText|20191029|X|X|X|3456
> OutboundManualCall|J|LALALA HTREDFST|FrulaalText|20191029|X|X|X|3456
> OutboundManualCall|H|RTYEHLA HTREDFSTFree"flow#Text20191029|X|X|X|3456