awk+;bash:组合任意数量的文件
我有一个脚本,它接受许多布局相同但数据不同的数据文件,并将指定的数据列合并到一个新文件中,如下所示:awk+;bash:组合任意数量的文件,bash,awk,gawk,Bash,Awk,Gawk,我有一个脚本,它接受许多布局相同但数据不同的数据文件,并将指定的数据列合并到一个新文件中,如下所示: gawk '{ names[$1]= 1; data[$1,ARGIND]= $2 } END { for (i in names) print i"\t"data[i,1]"\t"data[i,2]"\t"data[i,3] }' $1 $2 $3 > combined_data.txt 。。。行ID可以在第一列中找到,感兴趣的数据可以在
gawk '{
names[$1]= 1;
data[$1,ARGIND]= $2
} END {
for (i in names) print i"\t"data[i,1]"\t"data[i,2]"\t"data[i,3]
}' $1 $2 $3 > combined_data.txt
。。。行ID可以在第一列中找到,感兴趣的数据可以在第二列中找到
这很好,但不适用于任意数量的文件。虽然我可以简单地添加$4$5$n
在最后一行中,添加我认为需要的最大文件数,并添加相等的n
数量的“\t”数据[I,4]“\t”数据[I,5]。。。上面一行中的“\t”数据[i,n]
(这似乎适用于小于n
的文件;awk似乎忽略了n
在这些情况下大于输入文件的数量),这似乎是一个“丑陋”的解决方案。有没有办法让这个脚本(或给出相同结果的东西)接受任意数量的输入文件
或者,更好的是,您是否可以在其中合并一个find
,在子文件夹中搜索并查找与某些标准匹配的文件
以下是一些示例数据:
文件1
A 554
B 13
C 634
D 84
E 9
文件2:
C TRUE
E TRUE
F FALSE
预期产出:
A 554
B 13
C 634 TRUE
D 84
E 9 TRUE
F FALSE
您可以通过ARGV列表上的重定向getline访问任意数量的文件(绕过awk的默认文件处理(通过开始和退出)):
awk'开始{
对于(i=1;i您可以通过ARGV列表上的重定向getline访问任意数量的文件(绕过awk的默认文件处理(通过开始和退出)):
awk'开始{
对于(i=1;i您可以通过ARGV列表上的重定向getline访问任意数量的文件(绕过awk的默认文件处理(通过开始和退出)):
awk'开始{
对于(i=1;i您可以通过ARGV列表上的重定向getline访问任意数量的文件(绕过awk的默认文件处理(通过开始和退出)):
awk'开始{
对于(i=1;i假设输入文件的命名模式:1
2
gawk '{
names[$1]=$1
data[$1,ARGIND]=$2
}
END {
for (i in names) {
printf("%s\t",i)
for (x=1;x<=ARGIND;x++) {
printf("%s\t", data[i,x])
}
print ""
}
}' [0-9]* > combined_data.txt
假设输入文件的命名模式为:1
2
gawk '{
names[$1]=$1
data[$1,ARGIND]=$2
}
END {
for (i in names) {
printf("%s\t",i)
for (x=1;x<=ARGIND;x++) {
printf("%s\t", data[i,x])
}
print ""
}
}' [0-9]* > combined_data.txt
假设输入文件的命名模式为:1
2
gawk '{
names[$1]=$1
data[$1,ARGIND]=$2
}
END {
for (i in names) {
printf("%s\t",i)
for (x=1;x<=ARGIND;x++) {
printf("%s\t", data[i,x])
}
print ""
}
}' [0-9]* > combined_data.txt
假设输入文件的命名模式为:1
2
gawk '{
names[$1]=$1
data[$1,ARGIND]=$2
}
END {
for (i in names) {
printf("%s\t",i)
for (x=1;x<=ARGIND;x++) {
printf("%s\t", data[i,x])
}
print ""
}
}' [0-9]* > combined_data.txt
这可能就是您想要的(使用GNU awk作为ARGIND,就像您的原始脚本一样):
$cat tst.awk
开始{OFS=“\t”}
!已看到[$1]+{keys[++numKeys]=$1}
{vals[$1,argid]=$2}
结束{
对于(rowNr=1;rowNr这可能就是您要查找的内容(使用GNU awk作为ARGIND,就像您的原始脚本一样):
$cat tst.awk
开始{OFS=“\t”}
!已看到[$1]+{keys[++numKeys]=$1}
{vals[$1,argid]=$2}
结束{
对于(rowNr=1;rowNr这可能就是您要查找的内容(使用GNU awk作为ARGIND,就像您的原始脚本一样):
$cat tst.awk
开始{OFS=“\t”}
!已看到[$1]+{keys[++numKeys]=$1}
{vals[$1,argid]=$2}
结束{
对于(rowNr=1;rowNr这可能就是您要查找的内容(使用GNU awk作为ARGIND,就像您的原始脚本一样):
$cat tst.awk
开始{OFS=“\t”}
!已看到[$1]+{keys[++numKeys]=$1}
{vals[$1,argid]=$2}
结束{
对于(rowNr=1;rowNr另一个使用join
、bash
、awk
和tr
的解决方案,如果file1
、file2
、file3
等被排序
multijoin.sh
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
CMD="cat '$1'"
for i in `seq 2 $#`; do
CMD="$CMD | __t '${@:$i:1}'";
done
eval "$CMD | tr '_' '\t' | tr ' ' '\t'";
或者,递归版本
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
function __r {
if [[ "$#" -gt 1 ]]; then
__t "$1" | __r "${@:2}";
else
__t "$1";
fi
}
__r "${@:2}" < "$1" | tr '_' '\t' | tr ' ' '\t'
你得到
./multijoin file1 file2
A 554 111
B 13
C 634 TRUE
D 84 222
E 9 TRUE 333
F FALSE
A 554 111
B 13
C 634正确
D 84 222
E 9真的333
F错误
另一种解决方案是使用join
、bash
、awk
和tr
,如果对file1
、file2
、file3
等进行排序
multijoin.sh
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
CMD="cat '$1'"
for i in `seq 2 $#`; do
CMD="$CMD | __t '${@:$i:1}'";
done
eval "$CMD | tr '_' '\t' | tr ' ' '\t'";
或者,递归版本
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
function __r {
if [[ "$#" -gt 1 ]]; then
__t "$1" | __r "${@:2}";
else
__t "$1";
fi
}
__r "${@:2}" < "$1" | tr '_' '\t' | tr ' ' '\t'
你得到
./multijoin file1 file2
A 554 111
B 13
C 634 TRUE
D 84 222
E 9 TRUE 333
F FALSE
A 554 111
B 13
C 634正确
D 84 222
E 9真的333
F错误
另一种解决方案是使用join
、bash
、awk
和tr
,如果对file1
、file2
、file3
等进行排序
multijoin.sh
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
CMD="cat '$1'"
for i in `seq 2 $#`; do
CMD="$CMD | __t '${@:$i:1}'";
done
eval "$CMD | tr '_' '\t' | tr ' ' '\t'";
或者,递归版本
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
function __r {
if [[ "$#" -gt 1 ]]; then
__t "$1" | __r "${@:2}";
else
__t "$1";
fi
}
__r "${@:2}" < "$1" | tr '_' '\t' | tr ' ' '\t'
你得到
./multijoin file1 file2
A 554 111
B 13
C 634 TRUE
D 84 222
E 9 TRUE 333
F FALSE
A 554 111
B 13
C 634正确
D 84 222
E 9真的333
F错误
另一种解决方案是使用join
、bash
、awk
和tr
,如果对file1
、file2
、file3
等进行排序
multijoin.sh
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
CMD="cat '$1'"
for i in `seq 2 $#`; do
CMD="$CMD | __t '${@:$i:1}'";
done
eval "$CMD | tr '_' '\t' | tr ' ' '\t'";
或者,递归版本
#!/bin/bash
function __t {
join -a1 -a2 -o '1.1 2.1 1.2 2.2' - "$1" |
awk -vFS='[ ]' '{print ($1!=""?$1:$2),$3"_"$4;}';
}
function __r {
if [[ "$#" -gt 1 ]]; then
__t "$1" | __r "${@:2}";
else
__t "$1";
fi
}
__r "${@:2}" < "$1" | tr '_' '\t' | tr ' ' '\t'
你得到
./multijoin file1 file2
A 554 111
B 13
C 634 TRUE
D 84 222
E 9 TRUE 333
F FALSE
A 554 111
B 13
C 634正确
D 84 222
E 9真的333
F错误
编辑您的问题以显示具体的、可测试的样本输入和预期的输出。使用在我当前的实现中工作的一些可测试的样本输入进行编辑。我看到您添加了一个包含2个文件的示例,但您说过您的问题出现在3个以上的文件中,因此如果我们提供了一个适用于您发布的样本输入的解决方案,我们如何知道我f这真的足以解决您的问题吗?适用于任意数量文件的代码不应该同样适用于两个或三个输入文件吗?我的“问题”根本不会出现在任何地方,我只是认为我目前针对“许多输入文件”的解决方案是的,但适用于两个输入文件的代码不一定适用于任意数量的输入文件。一个能容纳20张床的房间可以容纳2张床,但一个能容纳2张床的房间不一定能容纳20张床。我不理解o部分如果你的问题是关于“n”的,大小和awk忽略了一些东西,所以我略读了一下,直接去寻找解决方案。编辑你的问题以显示具体的、可测试的样本输入和预期的输出。使用一些在我当前实现中有效的可测试样本输入进行编辑。我看到你添加了一个包含2个文件的示例,但你