【问题标题】:Copy a row from multiple files and paste as column in a new file从多个文件中复制一行并粘贴为新文件中的列
【发布时间】:2015-10-30 21:30:18
【问题描述】:

我的文件很少:

ifile1.txt       ifile2.txt       ifile3.txt
3  5  2  2       1  2  1  3       4  3  4  1 
1  4  2  1       1  3  0  2       5  3  1  5 
4  6  5  2       2  5  5  1       3  4  3  1 
5  5  7  1       0  0  1  1       4  3  4  0 
2  3  2  4       3  2  4  1       3  1  2  1

我需要从每个文件中复制第 4 行并将其作为列粘贴到 ofile.txt 中:

ofile.txt
5    0   4
5    0   3
7    1   4
1    1   0

我能够通过以下方式做到这一点,但正在寻找一种直接/简短的方法。

我首先使用awk将每个文件的行转换为列

awk '{ 
for (i=1; i<=NF; i++)  {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {    
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
    str=str" "a[i,j];
}
print str
}
}' ifile1.txt > ofile1.txt

然后我用paste命令作为

paste ofile* > ofile.txt

终于又用awk来打印需要的列了。

【问题讨论】:

    标签: linux shell awk


    【解决方案1】:

    正如Deepuhis good answer 中提到的那样,FNR==4 足以在每个文件上打印第四行:

    awk 'FNR==4' files*
    

    这样你会得到类似的东西

    5  5  7  1
    0  0  1  1
    4  3  4  0
    

    现在你只需要转置数组。为此,我创建了一个小脚本some time ago,我将其命名为transpose(非常擅长命名,我知道):

    transpose () {
    awk '{for (i=1; i<=NF; i++) a[i,NR]=$i; max=(max<NF?NF:max)}
            END {for (i=1; i<=max; i++)
                {for (j=1; j<=NR; j++) 
                    printf "%s%s", a[i,j], (j<NR?OFS:ORS)
                }
            }'
    }
    

    总而言之,你只需要说:

    $ awk 'FNR==4' f* | transpose
    5 0 4
    5 0 3
    7 1 4
    1 1 0
    

    请注意,如果您希望保持格式,可以设置输入和输出字段分隔符(我猜它们现在是制表符分隔的)。

    【讨论】:

    • 如果你有它(至少是 BSD 变体),rs 也可以用于转置。 awk 'FNR==4' f*.txt | rs -T
    • @jas 很有趣,我不知道这个工具。不过很遗憾,yum install rs 在我的电脑中没有找到任何东西:(
    • 确实,rs 看起来与便携相反! Mac OS X 有它,所以我认为它值得一提,但除了在兼容系统上一次性使用之外,你的作品无处不在的脚本是要走的路。
    • +1 我删除了我的答案,因为它非常相似(主要是我只是在 awk 脚本中提取了FNR==4)。需要注意的一件事是(j&lt;NR?OFS:ORS) 会比(j==NR?RS:FS) 更好,因为它在生成输出而不是输入分隔符时使用输出分隔符,并且它在代码中的 RS 之前声明了 FS,它与您的订单共同将输出它们,因此稍微提高了清晰度。 FWIW 我个人在编写循环遍历行和列的代码时会感到困惑,所以我倾向于将变量命名为 colNrrowNr(或 cr)至少是为了我自己的利益!
    • @EdMorton 哦,非常感谢您的建议!我将介绍它们并部署更改,因为我现在在许多答案中都使用此脚本:D(请保留评论,以便我稍后重新访问!)
    【解决方案2】:

    awk 'FNR == 4 {print}' 将从文本文件中打印第四行。

    您可以使用重定向运算符&gt; 和连接运算符&gt;&gt; 附加来自不同文件的数据。

    【讨论】:

      【解决方案3】:

      如果你的数据是规则的,这是另一种转置方式

      tr ' ' '\n' <file | pr -"$n"ts" "
      

      其中n 是文件中的行数(转置版本中的列)n 可以分配为

       n=$(wc -l file | cut -d" " -f1)
      

      您的脚本可以简化为

       awk 'FNR==4' ifile*.txt > temp
       n=$(wc -l temp | cut -d" " -f1)
       tr ' ' '\n' <temp | pr -"$n"ts" " > ofile.txt
      

      【讨论】:

        猜你喜欢
        • 2016-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-29
        • 1970-01-01
        • 2014-02-06
        • 2020-04-24
        相关资源
        最近更新 更多