如何去除竖线分隔字段中不需要的竖线符号- Linux

qoefvg9y  于 2023-03-01  发布在  Linux
关注(0)|答案(5)|浏览(224)

我这里有一个不寻常的。我们有一个管道分隔的文件与标题,但在第9字段(它拿起用户输入),我们可以偶尔得到一个用户键入管道符号。这抛出的格式文件完全出窗口,因为管道符号的数量现在不匹配的标题。见下面的例子-这是第5项下的EVNT_MSSG标题:

IDS|STG   |STT|WRKLST  |AR|CD   |DT    |INDX|EVNT_MSSG                                |EVNT_SRC|EVNT_TM |TYP|DATE    |USR_ID|IDS_APP
1  |ENRICH|Inc|complete|14|BM404|202302|15  |This is some text                        |Operator|10:33:13|0  |20230220|admin |3177098
2  |ENRICH|Inc|complete|15|BM501|202302|16  |This is some more                        |Operator|10:33:13|0  |20230220|admin |3177098
3  |ENRICH|Inc|complete|16|BM502|202302|17  |This bit is all good                     |Operator|10:33:13|0  |20230220|admin |3177098
4  |ENRICH|Inc|complete|17|BM551|202302|18  |Yet more text                            |Operator|10:33:13|0  |20230220|admin |3177098
5  |ENRICH|Inc|complete|18|EM002|202302|19  |problem here | pipes | not needed | Call |Operator|10:33:14|0  |20230220|admin |3177098
6  |ENRICH|Inc|complete|19|BM451|202302|20  |This is also fine                        |Operator|10:33:14|0  |20230220|admin |3177098

另外,在源代码处更改这一点将导致公司不愿意支付的成本,因此我的任务是提出一个解决方案,以消除第9个字段中的管道符号,同时保留所有其他字段的完整性。
我不幸碰了壁。
我在用|作为awk中的文件分隔符,以提取第9个字段ie

awk 'BEGIN { FS = "[|]+" } ; { print $9 }'

但是管道把这个扔掉了,因为他们把第一个不需要的管道看作是下一个合法的分隔符。我想我可能要从不同的Angular 来处理这个问题,但是还没有得到最模糊的地方去处理它。任何关于这个的帮助都将非常感激。

7cjasjjr

7cjasjjr1#

此解决方案适用于任何awk:

awk -v c=9 '
BEGIN {FS=OFS="|"}
NR == 1 {
   totCol = NF
   print
   next
}
diff = NF-totCol {
   s = ""   
   for (i=c; i<=NF; ++i) {
      if (i <= c+diff)
         s = s $i
      $i = $(i+diff)
   }
   NF = totCol
   $c = s
} 1' file

IDS|STG   |STT|WRKLST  |AR|CD   |DT    |INDX|EVNT_MSSG                                |EVNT_SRC|EVNT_TM |TYP|DATE    |USR_ID|IDS_APP
1  |ENRICH|Inc|complete|14|BM404|202302|15  |This is some text                        |Operator|10:33:13|0  |20230220|admin |3177098
2  |ENRICH|Inc|complete|15|BM501|202302|16  |This is some more                        |Operator|10:33:13|0  |20230220|admin |3177098
3  |ENRICH|Inc|complete|16|BM502|202302|17  |This bit is all good                     |Operator|10:33:13|0  |20230220|admin |3177098
4  |ENRICH|Inc|complete|17|BM551|202302|18  |Yet more text                            |Operator|10:33:13|0  |20230220|admin |3177098
5  |ENRICH|Inc|complete|18|EM002|202302|19  |problem here  pipes  not needed  Call |Operator|10:33:14|0  |20230220|admin |3177098
6  |ENRICH|Inc|complete|19|BM451|202302|20  |This is also fine                        |Operator|10:33:14|0  |20230220|admin |3177098
k4aesqcs

k4aesqcs2#

我将按照以下方式利用GNU AWK完成此任务,让file.txt内容

IDS|STG   |STT|WRKLST  |AR|CD   |DT    |INDX|EVNT_MSSG                                |EVNT_SRC|EVNT_TM |TYP|DATE    |USR_ID|IDS_APP
1  |ENRICH|Inc|complete|14|BM404|202302|15  |This is some text                        |Operator|10:33:13|0  |20230220|admin |3177098
2  |ENRICH|Inc|complete|15|BM501|202302|16  |This is some more                        |Operator|10:33:13|0  |20230220|admin |3177098
3  |ENRICH|Inc|complete|16|BM502|202302|17  |This bit is all good                     |Operator|10:33:13|0  |20230220|admin |3177098
4  |ENRICH|Inc|complete|17|BM551|202302|18  |Yet more text                            |Operator|10:33:13|0  |20230220|admin |3177098
5  |ENRICH|Inc|complete|18|EM002|202302|19  |problem here | pipes | not needed | Call |Operator|10:33:14|0  |20230220|admin |3177098
6  |ENRICH|Inc|complete|19|BM451|202302|20  |This is also fine                        |Operator|10:33:14|0  |20230220|admin |3177098

那么

awk 'BEGIN{FS=OFS=""}NR==1{split($0,arr)}{for(i=1;i<=NF;i+=1){if($i=="|"&&arr[i]!="|"){$i=" "}};print}' file.txt

给出输出

IDS|STG   |STT|WRKLST  |AR|CD   |DT    |INDX|EVNT_MSSG                                |EVNT_SRC|EVNT_TM |TYP|DATE    |USR_ID|IDS_APP
1  |ENRICH|Inc|complete|14|BM404|202302|15  |This is some text                        |Operator|10:33:13|0  |20230220|admin |3177098
2  |ENRICH|Inc|complete|15|BM501|202302|16  |This is some more                        |Operator|10:33:13|0  |20230220|admin |3177098
3  |ENRICH|Inc|complete|16|BM502|202302|17  |This bit is all good                     |Operator|10:33:13|0  |20230220|admin |3177098
4  |ENRICH|Inc|complete|17|BM551|202302|18  |Yet more text                            |Operator|10:33:13|0  |20230220|admin |3177098
5  |ENRICH|Inc|complete|18|EM002|202302|19  |problem here   pipes   not needed   Call |Operator|10:33:14|0  |20230220|admin |3177098
6  |ENRICH|Inc|complete|19|BM451|202302|20  |This is also fine                        |Operator|10:33:14|0  |20230220|admin |3177098

说明:我通知GNU AWK字段分隔符和输出字段分隔符都应该是空字符串,这导致每个字段都是一个字符宽。(NR==1)我使用split函数用列填充数组arr,然后,对于每一行,我在所有字段上迭代,并且如果我发现包含|的字段并且arr中的对应字段不包含|,我将该字段更改为空格字符。处理完字段I print行后。
(在GNU Awk 5.0.1中测试)

gdx19jrr

gdx19jrr3#

也许这种方法合适?

awk 'BEGIN{FS="|"}                                      # set field separator to pipe
     NF == 15 {print}                                   # if number of fields is correct, print the line
     NF > 15 {                                          # if NF is greater than expected i.e. extra pipes in $9
         for (i=1;i<=8; i++) {printf "%s|", $i}         # print the first 8 fields
         for (j=9; j<=(NF-6); j++) {printf "%s", $j}    # print the next N fields without a pipe delimiter
         for (k=(NF-5); k<=NF; k++) {printf "|%s", $k}  # print the last 6 fields
         print ""                                       # print a newline
     }' file

应用于示例数据:

IDS|STG   |STT|WRKLST  |AR|CD   |DT    |INDX|EVNT_MSSG                                |EVNT_SRC|EVNT_TM |TYP|DATE    |USR_ID|IDS_APP
1  |ENRICH|Inc|complete|14|BM404|202302|15  |This is some text                        |Operator|10:33:13|0  |20230220|admin |3177098
2  |ENRICH|Inc|complete|15|BM501|202302|16  |This is some more                        |Operator|10:33:13|0  |20230220|admin |3177098
3  |ENRICH|Inc|complete|16|BM502|202302|17  |This bit is all good                     |Operator|10:33:13|0  |20230220|admin |3177098
4  |ENRICH|Inc|complete|17|BM551|202302|18  |Yet more text                            |Operator|10:33:13|0  |20230220|admin |3177098
5  |ENRICH|Inc|complete|18|EM002|202302|19  |problem here   pipes  not needed Call |Operator|10:33:14|0  |20230220|admin |3177098
6  |ENRICH|Inc|complete|19|BM451|202302|20  |This is also fine                        |Operator|10:33:14|0  |20230220|admin |3177098
r6vfmomb

r6vfmomb4#

假设您有固定数量的字段,下面是一种可能的方法:

perl -pe 's/^([^|]*\|){8}\K.*?(?=(\|[^|]*){6}$)/$&=~s,\|,\\|,gr/e' ip.txt

这将在有问题的字段中用\|替换|
^([^|]*\|){8}\K将消耗前8个场,并且\K防止这成为匹配部分的一部分。
.*?延迟匹配零个或多个字符。
(?=(\|[^|]*){6}$)正前瞻,以确保最后6个字段未被修改。
e标志允许在替换部分使用Perl代码。在这种情况下,$&中的匹配部分将根据需要进行修改并返回。

ih99xse1

ih99xse15#

echo '

IDS|STG   |STT|WRKLST  |AR|CD   |DT    |INDX|EVNT_MSSG                                |EVNT_SRC|EVNT_TM |TYP|DATE    |USR_ID|IDS_APP
1  |ENRICH|Inc|complete|14|BM404|202302|15  |This is some text                        |Operator|10:33:13|0  |20230220|admin |3177098
2  |ENRICH|Inc|complete|15|BM501|202302|16  |This is some more                        |Operator|10:33:13|0  |20230220|admin |3177098
3  |ENRICH|Inc|complete|16|BM502|202302|17  |This bit is all good                     |Operator|10:33:13|0  |20230220|admin |3177098
4  |ENRICH|Inc|complete|17|BM551|202302|18  |Yet more text                            |Operator|10:33:13|0  |20230220|admin |3177098
5  |ENRICH|Inc|complete|18|EM002|202302|19  |problem here | pipes | not needed | Call |Operator|10:33:14|0  |20230220|admin |3177098
6  |ENRICH|Inc|complete|19|BM451|202302|20  |This is also fine                        |Operator|10:33:14|0  |20230220|admin |3177098' 

|
mawk NF=NF FS=' [|] ' OFS='   '
IDS|STG   |STT|WRKLST  |AR|CD   |DT    |INDX|EVNT_MSSG                                |EVNT_SRC|EVNT_TM |TYP|DATE    |USR_ID|IDS_APP
1  |ENRICH|Inc|complete|14|BM404|202302|15  |This is some text                        |Operator|10:33:13|0  |20230220|admin |3177098
2  |ENRICH|Inc|complete|15|BM501|202302|16  |This is some more                        |Operator|10:33:13|0  |20230220|admin |3177098
3  |ENRICH|Inc|complete|16|BM502|202302|17  |This bit is all good                     |Operator|10:33:13|0  |20230220|admin |3177098
4  |ENRICH|Inc|complete|17|BM551|202302|18  |Yet more text                            |Operator|10:33:13|0  |20230220|admin |3177098
5  |ENRICH|Inc|complete|18|EM002|202302|19  |problem here   pipes   not needed   Call |Operator|10:33:14|0  |20230220|admin |3177098
6  |ENRICH|Inc|complete|19|BM451|202302|20  |This is also fine                        |Operator|10:33:14|0  |20230220|admin |3177098

只要我们假设

      • 所有格式正确的字段左对齐**,

则这甚至对于可变宽度字段/列也将起作用。

相关问题