【问题标题】:Delete a column from a delimited file in linux从linux中的分隔文件中删除一列
【发布时间】:2012-09-24 20:20:07
【问题描述】:

我有一个格式如下的文件:

col1|col2|col3|col4
a|b|c|d
e|f||h
i|j|k|l

我想从标题和数据中删除 col3(带有分隔符“|”)。这可以使用 awk/sed 完成吗?

请注意 col3 中的数据可能为空(第 2 行)。

输出应该是:

col1|col2|col4
a|b|d
e|f|h
i|j|l

【问题讨论】:

  • 是的,这绝对可以用 sed 或 awk 完成。你试过什么?
  • awk -F"|" '{ OFS="|"; $3="";打印 }' in.txt > out.txt 但“|”被排除在外。我想要“|”跟随标题和数据消失了。

标签: linux unix awk sed


【解决方案1】:

如果您有很多列,另一个awk 解决方案可能会很有用

awk -F'|'  '{$3="";$0=$0;$3=$3}1' FPAT='[^|]+' OFS='|' file

【讨论】:

    【解决方案2】:

    cut 命令将有助于实现这一点

     cat filname | cut -d'|' -f1,2,4
    

    【讨论】:

    • 我没有发现任何问题,它工作正常。为什么被否决?
    • Useless cat 显然是个问题,并且可能会引起反对票。此外,考虑到这一点,这重复了我两年前的现有答案。
    【解决方案3】:

    这可能对你有用(GNU sed):

    sed 's/[^|]*|//3' file
    

    【讨论】:

    • 这是最好的解决方案。只需提及要删除的列号。在cut 中,您必须提及我们要保留在文件中的所有列。当您有 100 或 200 列时,sed 是有效的。你节省了我的时间......
    • 也许指出 GNU sed 不一定是您默认安装的 sed 版本,即使在某些版本的 Linux 上也是如此。
    【解决方案4】:

    使用cut 是正确的答案,但如果你真的想使用awk,它比Kent 显示的要容易:

    awk -F'|' 'BEGIN {OFS="|"} {for (n=3; n < NF; ++n) $n = $(n+1); --NF; print}'
    

    只需将$3 之后的字段打乱,然后通过更改NF 的值来更改字段数。

    【讨论】:

    • 谢谢乔纳森。我用过切。根据我的需要,这似乎是最简单直接的答案。
    【解决方案5】:

    这是一个可能的 sed 解决方案:

    sed -i.bak filename -e 's;\(^.*|.*|\).*|\(.*\);\1\2;'
    

    这对您的示例非常有用,并且可以针对其他示例进行调整,但并不是真正的通用解决方案。

    解释:

    -i.bak就地编辑文件,首先制作一个名为filename.bak的备份。

    \(^.*|.*|\) 从行首开始,匹配直到并包括第二个分隔符的所有内容。括号将此匹配分组(第 1 组)。

    .*| 匹配直到并包括最后一个分隔符的所有内容。

    \(.*\) 匹配其余和组(第 2 组)。

    \1\2 将之前的所有匹配项替换为第 1 组和第 2 组中的文本。

    【讨论】:

    • 我认为由于.* 表达式的贪婪,当您有超过4 个字段时,该表达式将不起作用。更通用的解决方案可能是:sed -i.bak filename -e 's;^\([^|]*|[^|]*|\)[^|]*|\(.*\);\1\2;'.
    • @JanitoVaqueiroFerreiraFilho 这绝对是一个更好的方法。
    • @JanitoVaqueiroFerreiraFilho 谢谢!但我真正的问题是该文件有 70 列,我想去掉第 45 列。那么,使用这种方法会不会变得很困难?
    【解决方案6】:
    awk  'BEGIN{FS=OFS="|"}{print $1,$2,$4}'   file
    

    应该给你输出。

    这是非常基本的 awk 用法。

    编辑

    你没有提到 70 列... :(

    试试这个:

    awk  -F'|' '{s="";for(i=1;i<=NF;i++){f=(NF==i)?"":FS;if(i!=3)s=s $i f;}print s}' file
    

    【讨论】:

    • 但我的文件有 70 列。有没有比写出除我需要的列(即 45 列)之外的所有列更好的方法
    • 谢谢肯特和三胞胎。感谢您的帮助。
    【解决方案7】:

    您可以简单地使用cut

    cut -d'|' -f1-2,4- file
    

    【讨论】:

    • 我需要纹身,上面写着“你试过剪吗?”
    • @Dean -- 切口不是更合适吗?
    • 一点注意,如果你有一个制表符分隔的文件,你可以在命令行上使用 -d $'\t' 来指定制表符。
    • @plugwash C 风格的字符串$'...' 是一个 Bash 扩展,因此它不能移植到 POSIX。但是,是的,如果 Bash-only 很好,你可以使用它。通常,您可以在许多 shell 中使用 ctrl-v 选项卡在命令行中获取文字选项卡。
    • ...当然,如果您有制表符分隔的数据,则根本不需要显式指定分隔符,因为制表符是cut中的默认分隔符。
    猜你喜欢
    • 1970-01-01
    • 2023-02-06
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多