用固定分隔符从N列中删除第5列

时间:2016-07-01 10:22:17

标签: awk

  1. 我有第N列的文件
  2. 我想从第N列的最后一列中删除第5列
  3. 分隔符是" |"
  4. 我用简单的例子进行了测试,如下所示:

    bash-3.2$ echo "1|2|3|4|5|6|7|8" | nawk -F\| '{print $(NF-4)}'
    4
    

    期待结果:

    1|2|3|5|6|7|8
    

    如何更改命令以获得所需的输出?

4 个答案:

答案 0 :(得分:2)

如果我理解正确,你想使用这样的东西:

sed -E 's/\|[^|]*((\|[^|]*){4})$/\1/'

这匹配管道字符\|后跟任意数量的非管道字符[^|]*,然后再捕获4个相同模式((\|[^|]*){4})。最后的$与行尾相匹配。匹配的第一部分(即结尾的第五个字段)被删除。

测试出来:

$ sed -E 's/\|[^|]*((\|[^|]*){4})$/\1/' <<<"1|2|3|4|5|6|7"
1|2|4|5|6|7

你可以使用gensub使用GNU awk来实现相同的功能,但我认为在这种情况下sed是正确的工具。

如果您的sed版本不支持使用-E扩展的正则表达式语法,则可以稍微修改它:

sed 's/|[^|]*\(\(|[^|]*\)\{4\}\)$/\1/'

在基本模式下,管道按字面解释,但是对于捕获组而言是括号,而卷曲的是用于转义。

答案 1 :(得分:1)

AWK 是您的朋友:

示例输入

A|B|C|D|E|F|G|H|I
A|B|C|D|E|F|G|H|I|A
A|B|C|D|E|F|G|H|I|F|E|D|O|R|Q|U|I
A|B|C|D|E|F|G|H|I|E|O|Q
A|B|C|D|E|F|G|H|I|X
A|B|C|D|E|F|G|H|I|J|K|L

<强>脚本

awk 'BEGIN{FS="|";OFS="|"}
      {$(NF-5)="";sub(/\|\|/,"|");print}' file

示例输出

A|B|C|E|F|G|H|I
A|B|C|D|F|G|H|I|A
A|B|C|D|E|F|G|H|I|F|E|O|R|Q|U|I
A|B|C|D|E|F|H|I|E|O|Q
A|B|C|D|F|G|H|I|X
A|B|C|D|E|F|H|I|J|K|L

我们在这里做了什么

  1. 如您所知,awk有特殊变量来存储记录中的每个字段,范围从$1$2$(NF)
  2. 从最后一列中排除第5个就像这样简单
    • 清空colume,即$(NF-5)=""
    • 从记录中删除上述步骤形成的连续|即{h} sub(/\|\|/,"|")

答案 2 :(得分:1)

另一种选择,使用@ sjsam的输入文件

$ rev file | cut -d'|' --complement -f6 | rev 

A|B|C|E|F|G|H|I
A|B|C|D|F|G|H|I|A
A|B|C|D|E|F|G|H|I|F|E|O|R|Q|U|I
A|B|C|D|E|F|H|I|E|O|Q
A|B|C|D|F|G|H|I|X
A|B|C|D|E|F|H|I|J|K|L

不确定你想要从最后一个或第六个开始的第5个。但它很容易调整。

答案 3 :(得分:0)

感谢您的帮助和指导。

以下是我测试的内容:

bash-3.2 $ echo&#34; 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9&#34; | nawk&#39; BEGIN {FS =&#34; |&#34 ;; OFS =&#34; |&#34;} {$(NF-4)=&#34;!&#34 ;;打印}&#39; | sed&#39; s / |!//&#39;

输出:1 | 2 | 3 | 4 | 6 | 7 | 8 | 9

对我从系统中提取的文件进行了进一步测试,因此工作正常。