【问题标题】:modify only one column of a big file and keep field seperator the same in unix仅修改大文件的一列并在 unix 中保持字段分隔符相同
【发布时间】:2013-05-08 09:41:20
【问题描述】:

我有一个非常大的文件(超过 10000 列)。我想更改第二列中的 3 个条目并保持其他内容不变,包括字段分隔符。

例如:

ab123\t123\t0.1
ab234\t120\t0.5

我想检查第二列是否有条目 120 并将其更改为 1201 并保持其他所有内容相同。

我试过 awk。它工作正常,但替换用空格分隔的制表符。

awk '{ if ( $2 == 120 ) { $2 = 1201 }; print}' file

如何在不丢失制表符分隔版本的情况下做到这一点?

【问题讨论】:

    标签: unix tabs awk field


    【解决方案1】:

    您想将FS(字段分隔符)OFS(输出字段分隔符)设置为制表符:

    awk '$2==120{$2=1201}1' FS='\t' OFS='\t' file
    

    OFS 是这里的重要变量,因为awk 使用它的值来分隔输出中的字段。

    编辑:

    awk 的结构是conditional{block},如果条件评估为 TRUE,则执行该块。因此,$2==120{$2=1201} 条件是 $2==120,如果第二个字段是值 120 并且块是 {$2=1201} 分配第二个字段值 1201。awk 中的默认块是 {print $0} 所以:

    awk '$2==120{$2=1201}{print $0}'
    

    可以改写为:

    awk '$2==120{$2=1201}1'
    

    其中 1 是始终评估为 TRUE 的条件,因为我们没有指定块,所以执行默认的 {print $0}

    对于多个条件,只需添加更多结构即:

    awk '$2==120{$2=1201}$3==130{$3==1301}1'
    

    这更像是一个if if 结构,因为两个块都可以执行,if else 将使用next 语句跳转到文件中的下一行即: em>

     awk '$2==120{$2=1201;next}{$2==1202}1'
    

    如果在这里执行第一个块,则第二个字段取值 1201,我们抓取下一行,否则第二个字段将取值 1202。所以第二个字段将始终取一个新值,12011202.

    if elif 将是:

    awk '$2==120{$2=1201;next}$3==130{$3==1301}1'
    

    这里第二个字段可能会取一个新值,如果是这样,第三个字段即使条件为真也不会更新,因为它永远不会被评估。仅当第一个条件为 FALSE 且第二个条件为 TRUE 时,才能更新第三个字段。

    【讨论】:

    • 谢谢@sudo_O,能否请您解释一下它的作用。 1是做什么的?您在任何地方都不需要 if 条件吗?以及如何将其扩展到多个条件?相当于'if - else if'的东西?
    • 还有@sudo_O,有没有办法检查字段分隔符是否是制表符分隔而不是视觉检查?
    • @user1007742 我不太清楚你的意思,如果你想直观地看到文件中的标签,那么你可以使用cat -T file,这会将标签显示为^I。跨度>
    【解决方案2】:
     sed -r 's/^ *[^ ]+ +120\b/\01/' file
    

    【讨论】:

    • 嗨@sidharth c nadhan,谢谢。这不会在整个文件中而不是仅在第二列中搜索和替换吗?
    • 正则表达式中的 120 之前只允许有一组空格。这确保它只替换第二列。
    猜你喜欢
    • 2020-11-24
    • 2015-03-05
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多