【问题标题】:Concatenation of two columns from the same file连接同一文件中的两列
【发布时间】:2017-05-25 14:48:45
【问题描述】:

来自文本文件

文件

a    d
b    e
c    f

制表符分隔的列如何连接成一列

a
b
c
d
e
f

现在我使用 awk 将列输出到两个文件,然后我使用 cat 将它们连接起来。但是一定有更好的单行命令?

【问题讨论】:

    标签: bash shell awk


    【解决方案1】:

    对于广义的方法

    $ f() { awk '{print $'$1'}' file; }; f 1; f 2
    
    a
    b
    c
    d
    e
    f
    

    如果文件是制表符分隔的,也许只是用cutpaste 的逆运算)

    $ cut -f1 file.t; cut -f2 file.t
    

    【讨论】:

    • cut 方法似乎是连接文件的最快方法。我将在一个有 6400 万行的文本文件上运行它,因此欢迎速度。
    【解决方案2】:

    您可以使用进程替换;这将消除为每列创建文件的需要。

    $ cat file 
    a    d
    b    e
    c    f
    $ cat <(awk '{print $1}' file) <(awk '{print $2}' file)
    a
    b
    c
    d
    e
    f
    $ 
    

    根据评论,您可以组合多个命令并将它们的输出重定向到不同的文件,如下所示:

    $ cat file 
    a    d
    b    e
    c    f
    $ (awk '{print $1}' file; awk '{print $2}' file) > output
    $ cat output 
    a
    b
    c
    d
    e
    f
    $
    

    【讨论】:

    • 在这种情况下,cat 看起来没用:(awk '{print $1}' file; awk '{print $2}' file) 应该足够了。
    • subshel​​l 也不需要,awk ..; awk .. 就可以了。
    【解决方案3】:

    try:无需两次读取文件或没有任何其他命令的任何外部调用,只需单个 awk 即可救援。还考虑到您的 Input_file 与显示的示例相同。

    awk '{VAL1=VAL1?VAL1 ORS $1:$1;VAL2=VAL2?VAL2 ORS $2:$2} END{print VAL1 ORS VAL2}'   Input_file
    

    解释:只需创建一个名为 VAL1 的变量,该变量将包含 $1 的值并继续连接它自己的值,VAL2 将拥有 $2 的值并继续连接它自己的值。在 awk 的 END 部分打印 VAL1 和 VAL2 的值。

    【讨论】:

      【解决方案4】:

      这个简单的 awk 命令应该可以完成这项工作:

      awk '{print $1; s=s $2 ORS} END{printf "%s", s}' file
      a
      b
      c
      d
      e
      f
      

      【讨论】:

      • 恕我直言,我认为 OP 请求的输出与上述不同,因为 OP 需要先打印 1 美元,然后再打印 2 美元。
      • 谢谢@RavinderSingh13,我忽略了那部分。现已更正。
      【解决方案5】:

      您可以将 bash 命令与 ; 结合使用以获取单个流:

      $ awk '{print $1}' file; awk '{print $2}' file
      a
      b
      c
      d
      e
      f
      

      如果您希望它是单个文件,请使用进程替换:

      $ txt=$(awk '{print $1}' file; awk '{print $2}' file)
      $ echo "$txt"
      a
      b
      c
      d
      e
      f
      

      或者对于 Bash while 循环:

      $ while read -r line; do echo "line: $line"; done < <(awk '{print $1}' file; awk '{print $2}' file)
      line: a
      line: b
      line: c
      line: d
      line: e
      line: f
      

      【讨论】:

        【解决方案6】:

        如果您使用的是 notepadd++,您可以将所有选项卡值替换为 newline char "\r\n"

        【讨论】:

        • 他在询问是否使用 bash 脚本(请参阅标签)。
        • 另外,这会交错列。
        【解决方案7】:

        另一种方法:

        for i in $(seq 1 2); do
            awk '{print $'$i'}' file
        done
        

        输出:

        a
        b
        c
        d
        e
        f
        

        【讨论】:

        • 这仅在输入恰好被排序时有效,但在一般情况下无效。
        • 它交错然后排序。假设输入看起来像a b\nc d。期望的输出是a\nc\nb\nd,但你的输出是a\nb\nc\nd
        • 分隔符插入在 $1 和 $2 之间,LF(\n) 不是文字值,具体取决于您插入的方式。这确实是 a\ndb\nec\nf
        • 与其他方法相比非常快。可能因为它只读取每一行一次。但如前所述,它不会连接列。但它可能非常有用。
        • 请将答案恢复为 0,尽管您更喜欢其他方法
        猜你喜欢
        • 1970-01-01
        • 2018-10-05
        • 2020-11-11
        • 1970-01-01
        • 2018-07-01
        • 2020-05-13
        • 2014-02-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多