根据两个文件的第一列比较两个文件并获取匹配和不匹配的行

根据两个文件的第一列比较两个文件并获取匹配和不匹配的行

我必须根据第一列比较两个制表符分隔的文件,如果第一列与第二个文件匹配,我必须打印第一个文件的整行。另外,我需要提取第一个文件中不存在但第二个文件中存在的那些条目。

文件1.txt:

chr1_45795114_G_A   0.004251803
chr1_45796900_G_C   0.019459893
chr1_45796909_C_T   0.003777726
chr1_45797139_G_A   0.006444843
chr12_56487682_T_A  0.003622254

文件2.txt:

chr12_56487682_T_A
chr19_9088697_T_C
chr11_108180929_T_-
chr1_45796909_C_T
chr19_9002597_C_T
chr1_45797139_G_A
chr1_45796900_G_C
chr2_48030697_T_G
chr7_151927025_A_G
chr1_45795114_G_A
chr1_211542902_G_-

期望的输出:

chr1_45795114_G_A   0.004251803
chr1_45796900_G_C   0.019459893
chr1_45796909_C_T   0.003777726
chr1_45797139_G_A   0.006444843
chr12_56487682_T_A  0.003622254
chr19_9088697_T_C   0
chr11_108180929_T_- 0
chr19_9002597_C_T   0
chr2_48030697_T_G   0
chr7_151927025_A_G  0
chr1_211542902_G_-  0

我尝试使用以下代码来实现我想要的输出。

代码 1 比较file1file2并从中提取匹配行file1

awk -F "\t" 'FNR==NR {a[$1]=$0; next}; $1 in a {print a[$1]}' file1 file2 > matching_rows.txt

代码 2 比较file1file2并从中提取不匹配的行file2

awk 'NR==FNR{a[$1]++;next;}!($0 in a)' file1 file2 > nonmatching_rows.txt

接下来,我连接matching_rows.txtnonmatching_rows.txt使用

cat matching_rows.txt nonmatching_rows.txt > combined.txt

现在,为了替换第二列中的空格,我使用了以下代码

awk 'NF && $2==""{$2=0}1' FS="\t" OFS="\t" combined.txt > desired_output.txt

我的问题是我必须将 100 多个文件与file2.是否可以将上述所有代码组合在一个脚本中,并根据文件名使用 for 循环运行它以获得所需的输出文件?

答案1

只需喂食awk- 包含两个文件的脚本。读取第一个文件时,填充一个存储 ID 值的数组。

读取第二个文件时,打印出每个 ID 以及之前存储的值。如果没有存储值,则打印出一个0.

FILENAME要区分当前读取的是哪个文件,请使用包含当前处理的文件名称的awk-Vaiable 。

awk'
        文件名==“文件1.txt”{
                # 只需将 id 填充到值数组中
                id = 1 美元
                值[id] = $2
        }
        文件名==“file2.txt”{
                id = 1 美元
                # 未设置的数组条目的默认内容是空字符串
                if (val[id] == "") {
                        # val[] 中没有存储任何值
                        打印 ID "\t" 0
                } 别的 {
                        打印 id "\t" val[id]
                }
        }
' 文件1.txt 文件2.txt

(请注意,上面的示例可能已优化,但我希望它易于理解。)

答案2

您可以使用 file1 的第一列作为 grep 命令的搜索模式。这将过滤掉 file2 中没有配对第二列的项目。

$ cp file1.txt outfile
$ awk '{print $1}' file1 > patterns

(模式是一个临时文件,您可以稍后删除)

然后:

$ grep -v -f patterns <file2 >>outfile
$ cat outfile
chr1_45795114_G_A   0.004251803
chr1_45796900_G_C   0.019459893
chr1_45796909_C_T   0.003777726
chr1_45797139_G_A   0.006444843
chr12_56487682_T_A  0.003622254
chr19_9088697_T_C
chr11_108180929_T_-
chr19_9002597_C_T
chr2_48030697_T_G
chr7_151927025_A_G
chr1_211542902_G_-

如果您必须在空的第二列中使用制表符分隔的零,则使用类似以下内容的内容:

$ awk 'NF==2{print $0} NF<2{print $1,"\t0"}' 输出文件

答案3

for file in f1 f2 f3 f4
do
awk 'NR==FNR{a[$1];next}($1 in a){print $0}' file2  $file >>output.txt
awk 'NR==FNR{a[$1];next}!($1 in a){print $0"\t""0" }' $file file2 >>output.txt
done

这里每次迭代的输出都保存在文件output.txt中

假设每个迭代输出都应保存在单独的文件中,那么我们需要遵循以下步骤

for file in f1 f2 f3 f4
do
awk 'NR==FNR{a[$1];next}($1 in a){print $0}' file2  $file >$file_file2
awk 'NR==FNR{a[$1];next}!($1 in a){print $0"\t""0" }' $file file2 >>$file_file2
done

相关内容