当文本与搜索字符串匹配时,删除管道分隔文件中的列

时间:2014-10-28 06:40:21

标签: unix

我需要在管道分隔文件中搜索特定文本,并删除与文本匹配的列。

例如: 我的档案

1|2|test123|3|4|5....|n
6|7|5|test123|10|11.....|n
6|7|1|9|test123|11.....|n

需要搜索包含“test”的列并删除该列

新文件应该看起来像

1|2|3|4|5....|n
6|7|5|10|11.....|n
6|7|1|9|11.....|n

我试过了

awk 'BEGIN{FS=OFS="|"}{$2=$3="";gsub(/[|]+/,"|")}1' test.txt >> test5.txt

命令,其中列号显式硬编码,但需要一个脚本来搜索文本然后删除列。

2 个答案:

答案 0 :(得分:0)

所有示例都使用数据文件:

1|2|test123|3|4|5....|n
6|7|5|test123|10|11.....|n
6|7|1|9|test123|11.....|n
test|1|2|3|4|5......|n
1|2|3|4|5|6.....|n-test-n
1|2|test|and-test-again|3|4|5|6.....|n-test-n

至少有两种方法可以解决这个问题。一个是纯文本的:替换一个序列管道,零个或多个非管道,单词'test',零个或多个非管道,以及另一个带有单个管道的管道:

awk '{ gsub(/\|[^|]*test[^|]*\|/, "|"); print }' test.txt >> test5.txt

输出:

1|2|3|4|5....|n
6|7|5|10|11.....|n
6|7|1|9|11.....|n
test|1|2|3|4|5......|n
1|2|3|4|5|6.....|n-test-n
1|2|and-test-again|3|4|5|6.....|n-test-n

鉴于'test'这个词可以出现在第一列或最后一列,你必须更加努力地处理这些:

awk '{ gsub(/\|[^|]*test[^|]*\|/, "|");  # Middle
       gsub(/^[^|]*test[^|]*\|/, "");    # Start
       gsub(/\|[^|]*test[^|]*$/, "");    # End
       print }' test.txt >> test5.txt

输出:

1|2|3|4|5....|n
6|7|5|10|11.....|n
6|7|1|9|11.....|n
1|2|3|4|5......|n
1|2|3|4|5|6.....
1|2|and-test-again|3|4|5|6.....

鉴于test可以出现在相邻字段中,您必须扫描两次以查找“中间”模式。

awk '{ gsub(/\|[^|]*test[^|]*\|/, "|");  # Middle - 1
       gsub(/\|[^|]*test[^|]*\|/, "|");  # Middle - 2
       gsub(/^[^|]*test[^|]*\|/, "");    # Start
       gsub(/\|[^|]*test[^|]*$/, "");    # End
       print }' test.txt >> test5.txt

输出:

1|2|3|4|5....|n
6|7|5|10|11.....|n
6|7|1|9|11.....|n
1|2|3|4|5......|n
1|2|3|4|5|6.....
1|2|3|4|5|6.....

另一种方法是扫描每一行的字段,而不是打印那些包含'test'的字段。

awk -F '|' \
    '{ pad = "";
       for (i = 1; i <= NF; i++)
       {
         if ($i !~ /test/)
         {
           printf("%s%s", pad, $i);
           pad = "|";
         }
       }
       print "";
     }' test.txt >> test5.txt

输出:

1|2|3|4|5....|n
6|7|5|10|11.....|n
6|7|1|9|11.....|n
1|2|3|4|5......|n
1|2|3|4|5|6.....
1|2|3|4|5|6.....

答案 1 :(得分:0)

file.txt的

1|2|test123|3|4|5....|n
6|7|5|test123|10|11.....|n
6|7|1|9|test123|11.....|n

脚本:

sed 's/test123|//' file.txt >> file1.txt