代码之家  ›  专栏  ›  技术社区  ›  Topher Fangio

使用可变分隔符数将字段换行

  •  1
  • Topher Fangio  · 技术社区  · 15 年前

    有些行有16个分隔符,因此16个字段是正确的,而有些行只有16个字段有18个分隔符。只有当第10个字段有18个分隔符而不是16个分隔符时,我才需要用引号将其括起来。我有一个可以使用awk、sed、grep等的Linux操作系统,我希望能有一种编写脚本的方法,这样我就不必手动操作了。

    只有5和7个分隔符(引用第4个字段)的输入/输出的简化示例如下:

    # Input
    
    Field 1|Field 2|Field 3|Field 4|Field 5|Field 6
    Field 1|Field 2|Field 3|Field | with | pipes|Field 5|Field 6
    
    # Output
    
    Field 1|Field 2|Field 3|Field 4|Field 5|Field 6
    Field 1|Field 2|Field 3|"Field | with | pipes"|Field 5|Field 6
    
    # Optional output if it is easier
    
    Field 1|Field 2|Field 3|"Field 4"|Field 5|Field 6
    Field 1|Field 2|Field 3|"Field | with | pipes"|Field 5|Field 6
    

    任何帮助都将不胜感激!

    2 回复  |  直到 15 年前
        1
  •  1
  •   ghostdog74    15 年前

    接吻。当您使用不同的字段和字段分隔符时,请使用像awk这样的工具,它完全适用于此工作。

    $ cat file
    Field 1|Field 2|Field 3|Field 4|Field 5|Field 6
    Field 1|Field 2|Field 3|Field | with | pipes|Field 5|Field 6
    
    $ awk -F"|" 'NF>6{$4="\042"$4 ; $(NF-2)=$(NF-2)"\042";}1' OFS="|"  file
    Field 1|Field 2|Field 3|Field 4|Field 5|Field 6
    Field 1|Field 2|Field 3|"Field | with | pipes"|Field 5|Field 6
    

    不需要使用复杂的正则表达式。

        2
  •  1
  •   Dennis Williamson    15 年前

    sed -i '/\([^|]*|\)\{7\}/{s/\([^|]*|\)/"\1/4;s/\(|[^|]*\)/"\1/6}' inputfile
    

    对于您的真实数据:

    sed -i '/\([^|]*|\)\{17\}/{s/\([^|]*|\)/"\1/14;s/\(|[^|]*\)/"\1/16}' inputfile
    

    (我在每个示例中添加了一对缺少的大括号,因此第二个 s 命令(实际上两者)只在地址匹配时运行。我还移除了 -n p p 消除重复。很抱歉出现错误。)

    s 命令在具有不同管道字符数的行上进行操作。

    • //
    • \(\)
    • [^|]* -零或更多( * )非管道( ^| [] -字符列表分隔符)
    • | -还有我们感兴趣的管道角色
    • \{7\}
    • {command; command} -这些大括号限定了当地址匹配时将要执行的命令块—地址和大括号的行为就像 if 语句及其关联块

    然后是第一个 s 命令要求将第4个(或第14个)管道字符及其前面的非管道字符替换为引号,后跟匹配的字符。

    sed 要求对多命令单行脚本使用'sed-e'command'-e'command'形式,而不是分号。

    s 是一个命令,而不是regex的一部分。上面命令中的初始斜杠对之间的部分和 s///

    如果您还有其他问题,请告诉我。 第二个 s 命令将查找第6个(或第16个)管道字符以及其后的零个或多个非管道,并将其替换为自身(匹配的字符)和引号。

    推荐文章