【问题标题】:Same column of different files into the same new file不同文件的同一列放入同一个新文件
【发布时间】:2015-01-22 10:09:13
【问题描述】:

我有多个文件夹 Case-1、Case-2....Case-N,它们都有一个名为 PPD 的文件。我想提取所有第二列并将它们放入一个名为 123.dat 的文件中。 看来我不能在 for 循环中使用 awk。

case=$1
for (( i = 1; i <= $case ; i ++ ))
do
    file=Case-$i
    cp $file/PPD temp$i.dat

    awk 'FNR==1{f++}{a[f,FNR]=$2}
         END
         {for(x=1;x<=FNR;x++)
             {for(y=1;y<ARGC;y++)
             printf("%s ",a[y,x]);print ""} }'  

    temp$i.dat >> 123.dat   
done

现在 123.dat 仅包含 Case-N 中最后一个 PPD 的日期

如果每个 PPD 文件至少有一列相同,我知道我可以使用 join(我之前使用过该命令),但如果我有很多 Case 文件夹,它会变得非常慢

【问题讨论】:

    标签: loops for-loop awk


    【解决方案1】:

    外部 shell 脚本和内部 awk 调用之间的交互没有按您预期的方式工作。

    每次循环,shell 脚本都会调用awk 一个新的时间,这意味着f 将被取消设置,然后第一个子句将其设置为1。它永远不会变成2。也就是说,您为通过外循环的每次迭代启动一个新的awk 进程,而awk 每次都从头开始。

    还有其他方法来构建代码,但作为一个最小的调整,您可以使用 -v 选项将数字 $i 传递给 awk 调用,例如awk -v i="$i" ....

    请注意,正如其他回答者已经建议的那样,有更好的方法来构建您的整体解决方案;我的意思是这个回答是对这个问题的回答,“为什么这不起作用?”而不是“请重写此代码。”

    【讨论】:

    • 嗨,danfuzz,你能更准确地解释一下吗?我是新手,我每天只使用 Fortran。谢谢
    • 扩大了我的答案。
    【解决方案2】:

    也许

    eval paste $(printf ' <(cut -f2 %s)' Case-*/PPD)
    

    您一次可以执行多少个进程替换可能存在限制。我用 20 列做到了这一点,这很好。进程替换是 Bash 的一项功能,因此通常不能移植到其他与 Bourne 兼容的 shell。

    通配符将按字母顺序展开。如果您希望按数字顺序排列案例,可以使用case-[1-9] case-[1-9][0-9] case-[1-9][0-9][0-9] 强制扩展首先获得个位数,然后是两位数,等等。

    【讨论】:

    • ksh93+ 现在支持进程替换很长一段时间了 好东西! ;-)
    • 这就是为什么我谨慎地使用“一般”。感谢您的评论。
    【解决方案3】:

    下面的AWK 程序可以帮助你。

    #!/usr/bin/awk -f
    
    BEGIN {
        # Defaults
        nrecord=1
        nfiles=0
    }
    
    BEGINFILE {
        # Check if the input file is accessible,
        # if not skip the file and print error.
        if (ERRNO != "") {
            print("Error: ",FILENAME, ERRNO)
            nextfile
        }
    }
    
    {
        # Check if the file is accessed for the first time
        # if so then increment nfiles. This is to keep count of
        # number of files processed.
        if ( FNR == 1 ) {
            nfiles++
        } else if (FNR > nrecord) {
            # Fetching the maximum size of the record processed so far.
            nrecord=FNR
        }
    
        # Fetch the second column from the file.
        array[nfiles,FNR]=$2
    
    }
    
    END {
        # Iterate through the array and print the records.
        for (i=1; i<=nrecord; i++) {
            for (j=1; j<=nfiles; j++) {
                printf("%5s", array[j,i])
            }
            print ""
        }
    }
    

    输出:

    $ ./get.awk Case-*/PPD
        1   11   21
        2   12   22
        3   13   23
        4   14   24
        5   15   25
        6   16   26
        7   17   27
        8   18   28
        9   19   29
       10   20   30
    

    这里的Case*/PPD 扩展为Case-1/PPDCase-2/PPDCase-3/PPD 等等。以下是为其生成输出的源文件。

    $ cat Case-1/PPD 
    1   1   1   1
    2   2   2   2
    3   3   3   3
    4   4   4   4
    5   5   5   5
    6   6   6   6
    7   7   7   7
    8   8   8   8
    9   9   9   9
    10  10  10  10
    $ cat Case-2/PPD 
    11  11  11  11
    12  12  12  12
    13  13  13  13
    14  14  14  14
    15  15  15  15
    16  16  16  16
    17  17  17  17
    18  18  18  18
    19  19  19  19
    20  20  20  20
    $ cat Case-3/PPD 
    21  21  21  21
    22  22  22  22
    23  23  23  23
    24  24  24  24
    25  25  25  25
    26  26  26  26
    27  27  27  27
    28  28  28  28
    29  29  29  29
    30  30  30  30
    

    【讨论】:

    • 这不会产生相邻的列,只会产生不同连续行上不同文件的输出。
    • 谢谢,但它不能并排放置数据,我的最终目的是取平均值,所以我的最后一步是$1+$2+......$N,所以我需要将它们并排放置。
    • @user3065582 我已经更新了AWK 程序以满足您的需要。看看这是否有帮助..
    猜你喜欢
    • 2012-05-04
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多