将不同文件的每 3 列添加到一个文件中
Add every 3rd column of different files into one file
我是 awk 的新手,所以我希望有人能提供帮助
我有 55 个文本文件(在 TAB 中,并且具有类似的以 .txt 结尾的命名),所有文件都恰好包含 55 行和 4 列。没有行或列丢失。唯一的区别是文件中的值。它们看起来像下面的(现在只包含 4 行和 3 个文件)
Row1 355 389 623
Row2 58 906 1373
Row3 338 3 30
Row4 2 976 0
Row1 543 31 6642
Row2 0 0 453
Row3 45 5 42
Row4 425 12 8
Row1 452 6 352
Row2 765 21 54
Row3 0 45 999
Row4 451 765 3
我想添加一次第一列(名称),然后将所有文件中的每第 3 列添加到一个。 编辑:如果可能,文件名 输出应如下所示:
1.txt 2.txt 3.txt
Row1 389 31 6
Row2 905 0 21
Row3 3 5 45
Row4 976 12 765
我试过这个代码
paste * | awk 'FNR==NR{a[FNR]=; next} {print a[FNR],}' *.txt > output.txt | column -t
但是,它只增加了前两个文件的值。来自其他文件的值不存在。我能做什么?谢谢!
你可以试试这个 awk:
awk -F '\t' '
FNR==NR {table[FNR] = }
{table[FNR] = table[FNR] "\t" }
END {
for (i=1; i<=FNR; i++) {
print table[i]
}
}' *
FNR 的最后一个(第 55 个)值用于打印数组,因此如果文件的行数不同,您将需要解决这个问题。
如果你想使用paste
,可能是这样的:
paste * |
awk '
{
printf "%s",
for (i=3; i<55*4; i+=4) {
printf "\t%s", $i
}
printf "\n"
}'
55*4
是文件数乘以列数。硬编码。如有必要,有多种方法可以计算这些。
假设:
- input/output 字段分隔符是
<TAB>
- 所有输入文件包含相同的行数
- 所有行至少有 3 列
- 不需要对输入文件进行排序(即,
Row1
总是在第 1 行,Row2
总是在第 2 行,等等)
*.txt
将扩展为所需顺序的文件列表(例如,1.txt1
、2.txt
、3.txt
等);否则 OP 可能需要在将文件名提供给建议的解决方案之前对文件名进行预排序
一个awk
想法:
awk '
BEGIN { FS=OFS="\t" } # input/output field delimiter is <TAB>
FNR==1 { lines[0]=lines[0] OFS FILENAME } # append filename to "header" record
FNR==NR { lines[FNR]= } # save the "RowN" string
{ lines[FNR]=lines[FNR] OFS } # append field #3 to the line
END { for (i=0;i<=FNR;i++) # loop through the line numbers ...
print lines[i] # printing each line to stdout
}
' *.txt
假设 3 个示例输入文件被命名为 {1..3}.txt
此 awk
脚本生成:
1.txt 2.txt 3.txt
Row1 389 31 6
Row2 906 0 21
Row3 3 5 45
Row4 976 12 765
我是 awk 的新手,所以我希望有人能提供帮助
我有 55 个文本文件(在 TAB 中,并且具有类似的以 .txt 结尾的命名),所有文件都恰好包含 55 行和 4 列。没有行或列丢失。唯一的区别是文件中的值。它们看起来像下面的(现在只包含 4 行和 3 个文件)
Row1 355 389 623
Row2 58 906 1373
Row3 338 3 30
Row4 2 976 0
Row1 543 31 6642
Row2 0 0 453
Row3 45 5 42
Row4 425 12 8
Row1 452 6 352
Row2 765 21 54
Row3 0 45 999
Row4 451 765 3
我想添加一次第一列(名称),然后将所有文件中的每第 3 列添加到一个。 编辑:如果可能,文件名 输出应如下所示:
1.txt 2.txt 3.txt
Row1 389 31 6
Row2 905 0 21
Row3 3 5 45
Row4 976 12 765
我试过这个代码
paste * | awk 'FNR==NR{a[FNR]=; next} {print a[FNR],}' *.txt > output.txt | column -t
但是,它只增加了前两个文件的值。来自其他文件的值不存在。我能做什么?谢谢!
你可以试试这个 awk:
awk -F '\t' '
FNR==NR {table[FNR] = }
{table[FNR] = table[FNR] "\t" }
END {
for (i=1; i<=FNR; i++) {
print table[i]
}
}' *
FNR 的最后一个(第 55 个)值用于打印数组,因此如果文件的行数不同,您将需要解决这个问题。
如果你想使用paste
,可能是这样的:
paste * |
awk '
{
printf "%s",
for (i=3; i<55*4; i+=4) {
printf "\t%s", $i
}
printf "\n"
}'
55*4
是文件数乘以列数。硬编码。如有必要,有多种方法可以计算这些。
假设:
- input/output 字段分隔符是
<TAB>
- 所有输入文件包含相同的行数
- 所有行至少有 3 列
- 不需要对输入文件进行排序(即,
Row1
总是在第 1 行,Row2
总是在第 2 行,等等) *.txt
将扩展为所需顺序的文件列表(例如,1.txt1
、2.txt
、3.txt
等);否则 OP 可能需要在将文件名提供给建议的解决方案之前对文件名进行预排序
一个awk
想法:
awk '
BEGIN { FS=OFS="\t" } # input/output field delimiter is <TAB>
FNR==1 { lines[0]=lines[0] OFS FILENAME } # append filename to "header" record
FNR==NR { lines[FNR]= } # save the "RowN" string
{ lines[FNR]=lines[FNR] OFS } # append field #3 to the line
END { for (i=0;i<=FNR;i++) # loop through the line numbers ...
print lines[i] # printing each line to stdout
}
' *.txt
假设 3 个示例输入文件被命名为 {1..3}.txt
此 awk
脚本生成:
1.txt 2.txt 3.txt
Row1 389 31 6
Row2 906 0 21
Row3 3 5 45
Row4 976 12 765