【问题标题】:How to insert additional field after third field if number of field separators in line is 5 using sed or awk如果使用 sed 或 awk 行中的字段分隔符数为 5,如何在第三个字段之后插入附加字段
【发布时间】:2016-02-20 13:59:30
【问题描述】:

是否可以运行一个 sed 命令来检查一行中的字段分隔符的数量,并在该行中的分隔符数量为 5 时插入一个额外的分隔符,例如?

源数据示例:

a,aaa|bbbb|cccc|dddd|eeee|ffff|gggg
aaaa|bb,bb|dddd|eeee|fff,f|gggg
aaa,a|bbbb|cccc|dddd|eeee|ffff|gggg

目标输出示例:

a,aaa|bbbb|cccc|dddd|eeee|ffff|gggg
aaaa|bb,bb||dddd|eeee|fff,f|gggg
aaa,a|bbbb|cccc|dddd|eeee|ffff|gggg

注意:如果该行中仅存在 5 个字段分隔符,则目标是在该行的第二个字段分隔符之前或之后立即插入一个额外的字段分隔符 (|) 以创建一个空白的第三个字段。

如果使用 sed 无法做到这一点,awk 是否能够完成任务?

任何指导将不胜感激。

【问题讨论】:

    标签: regex awk sed


    【解决方案1】:

    这样的事情应该可以工作:

    awk -F '|' -v OFS='|' 'NF<7{$2=$2 FS} 1'
    

    -F '|' 将输入字段分隔符设置为|
    -v OFS='|' 将输出字段分隔符设置为|

    当字段数NF小于7时,在第二个字段后追加字段分隔符FS。

    【讨论】:

    • 我相信OP需要awk -F '|' -v OFS='|' 'NF==6{$2=$2 FS} 1' file
    • @anubhava:不管是不是,OP已经消失了。
    • 当您有 2 个必须具有相同值的变量时,为了清晰和维护,最好将它们设置在一起而不是单独设置为相同的值:awk 'BEGIN{FS=OFS="|"} NF&lt;7{$2=$2 FS} 1'。我真希望当他们发明 awk 时,-FFS 表示输入和输出分隔符,而 IFS 是输入(如在 shell 中)和 OFS 是输出,所以只有一件事当您希望它们都相同但那艘船在 40 年前航行时,设置为像这样的常见情况....
    • @Casimir et Hippolyte、anubhava 和 Ed Morton:抱歉延迟回复。感谢您的输入。非常感激。 :)
    【解决方案2】:

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

    sed 's/|/&/6;t;s/|/&&/2' file
    

    如果字段分隔符的数量(在本例中为 6 个)足够,请退出。
    否则,将必填字段上的字段分隔符加倍(在本例中为 2)。

    如果您只想在正好有五个时添加分隔符,请使用:

    sed 's/|/&/6;t;s/|/&/5;T;s/|/&&/2' file
    

    【讨论】:

    • ++;只是为第二个命令添加一个解释:s/|/&amp;/6;t 是一个(有效的)无操作,如果存在第 6 个分隔符(如果在该行上找到 6 个或更多分隔符),则跳过剩余的命令; s/|/&amp;/5;T 是跳过剩余命令的空操作,如果找到 no 第 5 个分隔符。因此,s/|/&amp;&amp;/3 仅对具有 恰好 5 个分隔符的行执行,并执行请求的第二个分隔符加倍。
    【解决方案3】:

    用 sed 肯定是可能的:

    sed '/^[^|]*\(|[^|]*\)\{5\}$/s/|/||/2'
    

    5 是将触发替换的分隔符的数量,而行尾的 2 是将发生替换的分隔符计数。

    这已经比我最初的尝试更具可读性和很多更易于维护:

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

    不过,就可读性而言,awk 解决方案是最好的。

    【讨论】:

    • 您好 Ruud,感谢您的反馈。这适用于该特定实例。我还需要将逻辑应用于其他场景。你能解释一下命令是如何分解的吗?
    • sed '/^[^|]*(|[^|]*)\{5\}$/s/|/||/2'
    • 我已经能够调整它以适用于其他场景。第二个版本我一直没能适应。你能解释一下它是如何工作的吗?
    • 第二个命令使用一个由两个括号部分组成的正则表达式;第一部分匹配aa|bb,第二部分匹配|dd|ee|ff|gg。替换部件用一个额外的分隔符将它们缝合在一起。
    猜你喜欢
    • 2023-03-14
    • 2015-01-26
    • 1970-01-01
    • 2012-04-07
    • 2014-10-14
    • 2011-02-06
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    相关资源
    最近更新 更多