unix 不同目录中相同文件的最后一列的水平连接

5cnsuln7  于 2023-10-18  发布在  Unix
关注(0)|答案(2)|浏览(174)

我试图通过800个子目录和解析的最后一列的一个特定的文件(myfile.txt)在所有子目录相同的名称/结构,并打印这些列水平在一个单一的输出文件。下面是3个文件的示例。

(myfile.txt) in dir_1
Row1      44.4            
Row2      45.5        
Row3      46.2           
Row4      46.3
(myfile.txt) in dir_2
Row1      33.7
Row2      25.8
Row3      14.9
Row4      32.1
(myfile.txt) in dir_3
Row1      12.1
Row2      13.2
Row3      14.5
Row4      16.4

感谢@markp-fuso,我修改了他的脚本如下。但输出不是我所期望的。

awk '
BEGIN { OFS="\t" }
      { lines[FNR]= lines[FNR] (FNR==NR ? "" : OFS) $2 }
END   { for (i=1; i<=FNR; i++)
            print lines[i]
      }
' dir_*/myfile.txt > out.txt

生成输出:

44.4            
45.5        
46.2           
46.3
33.7
25.8
14.9
32.1
32.1
12.1
13.2
14.5

预期输出(已更正):

44.4   33.7   12.1       
45.5   25.8   13.2  
46.2   14.9   14.5     
46.3   32.1   16.4
jk9hmnmh

jk9hmnmh1#

在单独的目录中使用输入文件-

$: grep . ?/myfile.txt
a/myfile.txt:Row1      44.4
a/myfile.txt:Row2      45.5
a/myfile.txt:Row3      46.2
a/myfile.txt:Row4      46.3
b/myfile.txt:Row1      33.7
b/myfile.txt:Row2      25.8
b/myfile.txt:Row3      14.9
b/myfile.txt:Row4      32.1
c/myfile.txt:Row1      12.1
c/myfile.txt:Row2      13.2
c/myfile.txt:Row3      14.5
c/myfile.txt:Row4      16.4

这在awk中很简单:

$: awk '{line[FNR]=line[FNR]$NF"\t"} END{for(row in line)print line[row]}' ?/myfile.txt
44.4    33.7    12.1
45.5    25.8    13.2
46.2    14.9    14.5
46.3    32.1    16.4

打破这一点:
{ line[FNR] = line[FNR] $NF "\t" }
FNR是“记录的文件号”,所以在第1行它将是1。
NF是“字段数”,因此$NF始终是最后一个字段。
这将在每一行上,为该行的数组分配任何以前的内容(第一个文件没有),然后连接最后一个字段的值,然后是一个选项卡(或任何其他你喜欢的选项卡)。如果这不是真的,那么逻辑就有点复杂了。
END{ for (row in line) print line[row] }
这将数组line中每个现有值的索引赋给row,然后将其用于print该单元格的内容,这将在末尾添加一个换行符。它留下了悬挂的翅膀;如果这是一个问题,我们可以修剪它,
print gensub(/\t$/,"",1,line[row])
而不是仅仅
print line[row]
?/myfile.txt可以是生成适当文件列表的任何glob。如果你不能创建一个有效的glob,我们需要提供文件列表。
如果你需要任意深度的globbing,请先尝试设置shopt -s globstar;然后使用/base/path/**/myfile.txt(只要在你的/base/path/下没有你不想包含的myfile.txt)。

bvn4nwqk

bvn4nwqk2#

这里有一个ruby来做这件事。
一切,包括递归的globbing,都是由Ruby完成的。
您需要有足够的内存来保存内存中的所有文件。
给出:

head **/myfile.txt
==> dir_1/myfile.txt <==
Row1      44.4            
Row2      45.5        
Row3      46.2           
Row4      46.3

==> dir_2/myfile.txt <==
Row1      33.7
Row2      25.8
Row3      14.9
Row4      32.1

==> dir_3/myfile.txt <==
Row1      12.1
Row2      13.2
Row3      14.5
Row4      16.4

您可以执行以下操作:

ruby -e 'di=Dir.glob("**/myfile.txt").
            map{|fn| File.open(fn).read.split(/\R/).
            map(&:split).
            map(&:last)}.flatten
rows=di.each_slice(3).to_a.length
di.each_slice(rows).to_a.transpose.each{|r| puts r.join("\t")}'

图纸:

44.4    33.7    12.1
45.5    25.8    13.2
46.2    14.9    14.5
46.3    32.1    16.4

确保在所有感兴趣的文件的父目录中执行。
假设文件的长度不同,并且您希望每个文件都有一列。
给出:

head */myfile.txt
==> dir_1/myfile.txt <==
Row1      44.4            
Row2      45.5        
Row3      46.2           
Row4      46.3

==> dir_2/myfile.txt <==
Row1      33.7
Row2      25.8
Row3      14.9
Row4      32.1

==> dir_3/myfile.txt <==
Row1      12.1
Row2      13.2
Row3      14.5
Row4      16.4
Row5      xxxx

您可以执行以下操作:

ruby -e '
fns={}
ARGV.each{|fn| fns[fn]=File.open(fn)}
loop do
    puts ARGV.map{|fn| fns[fn].eof? ? "NA" : fns[fn].readline.split.last}.join("\t")
    break if ARGV.map{|fn| fns[fn].eof?}.all?
end' **/myfile.txt | column -t

图纸:

44.4  33.7  12.1
45.5  25.8  13.2
46.2  14.9  14.5
46.3  32.1  16.4
NA    NA    xxxx

相关问题