我必须根据第一列比较两个制表符分隔的文件,如果第一列与第二个文件匹配,我必须打印第一个文件的整行。另外,我需要提取第一个文件中不存在但第二个文件中存在的那些条目。
文件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 比较file1
和file2
并从中提取匹配行file1
:
awk -F "\t" 'FNR==NR {a[$1]=$0; next}; $1 in a {print a[$1]}' file1 file2 > matching_rows.txt
代码 2 比较file1
和file2
并从中提取不匹配的行file2
:
awk 'NR==FNR{a[$1]++;next;}!($0 in a)' file1 file2 > nonmatching_rows.txt
接下来,我连接matching_rows.txt
并nonmatching_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