我需要帮助将一个文件(File-1.txt)中的值(数字)替换为另一个文件(File-2)中的值(字符串),其中包含第一列中的值和第二列中的相应名称。这两个文件如下:
文件-1.txt的
(0, ':', [])
(1, ':', [18])
(2, ':', [20, 41])
(3, ':', [18])
(4, ':', [17])
(5, ':', [])
(6, ':', [])
文件-2.txt
1 ALA_A_87
2 THR_A_127
3 GLY_A_128
4 ILE_A_130
5 THR_A_166
6 THR_A_167
预期产出:
(ALA_A_87, ':', [THR_A_127])
(THR_A_127, ':', [ALA_A_87, GLY_A_128, ILE_A_130])
(GLY_A_128, ':', [THR_A_127, 5])
(ILE_A_130, ':', [THR_A_127])
(THR_A_166, ':', [GLY_A_128, THR_A_167])
(THR_A_167, ':', [THR_A_166])
我一直在尝试一些awk代码,但没有运气! awk代码如下:
awk -F, '
BEGIN {
subs="ALA_A_87 THR_A_127 GLY_A_128 ILE_A_130 THR_A_166 THR_A_167";
split( subs, subs_arr );
}
NR == 1 {
print;
next
}
NR>1{
for i in {1 2 3 4 5 6 }; {
$i = subs_arr[ $i++ ];
}
print
}
' File-1.txt
在这里,我提供了代码本身要替换的名称和值,但是如果它可以作为外部文件(File-2.txt)提供,并将File-1.txt中的数字与File-2.txt的第一列,将File-1.txt中的数字替换为File-2.txt中显示的相应名称。帮我解决这个问题。
提前致谢
答案 0 :(得分:1)
我真的不确定哪些号码应该被替换,但是这个号码取代了[]
内的号码,因为它感觉更有趣。您应始终提供预期结果:
$ awk 'NR==FNR { a[$1]=$2; next }
{
b=$0;
gsub(/^.*\[|\].*$/,"",b);
if(split(b,c,", "))
for(i in c)
sub(c[i],a[c[i]],b);
sub(/\[.*\]/,"[" b "]",$0)
} 1' f2 f1
(0, ':', [])
(1, ':', [GLY_B_235])
(2, ':', [CYS_B_237, SER_D_310])
(3, ':', [GLY_B_235])
(4, ':', [ASP_B_234])
...
修改:为@NeronLeVelu添加了一个版本:
$ awk 'NR==FNR { a[$1]=$2; next }
{ for(i=2;++i<=NF;)
sub(/[0-9]+/,a[substr($i,match($i,/[0-9]+/),RLENGTH)],$i)
} 1' f2 f1
(0, ':', [])
(1, ':', [GLY_B_235])
(2, ':', [CYS_B_237, SER_D_310])
(3, ':', [GLY_B_235])
(4, ':', [ASP_B_234])
...
其他修改:在澄清要求(2
- &gt; 0
)之后,这是工作版本:
$ awk 'NR==FNR { a[$1]=$2; next }
{ for(i=0;++i<=NF;)
sub(/[0-9]+/,a[substr($i,match($i,/[0-9]+/),RLENGTH)],$i)
} 1' f2 f1
(, ':', [])
(ALA_A_87, ':', [GLY_B_235])
(THR_A_127, ':', [CYS_B_237, SER_D_310])
(GLY_A_128, ':', [GLY_B_235])
(ILE_A_130, ':', [ASP_B_234])
答案 1 :(得分:1)
如果这是要替换
的名称的file2的第二部分awk 'FNR==NR{n[$1]=$2;next}
{
h=$0;gsub( /\[.*/, "[", h)
N=$0;gsub( /.*\[|].*/, "", N)
NsS = split( N, aNs, /,[[:blank:]]*/)
printf( "%s", h)
for ( i=1; i<=NsS; i++) printf( "%s%s", (i==1 ? "" : ", "), n[aNs[i]])
printf( "]\n")
}
' File-2.txt File-1.txt
詹姆斯·布朗的速度与能力的挑战,第二个版本: - )
awk -F '[][[:blank:],]*' '
FNR==NR{split($0,t,/[[:blank:]]*/);n[t[1]]=t[2];next}
{
printf( "%s, %s, [",$1, $2)
for ( i=3; i<NF; i++) printf( "%s%s", (i==3 ? "" : ", "), n[$i])
printf( "])\n")
}
' File-2.txt File-1.txt
回复内部&#34;挑战&#34;使用@JamesBrown和最后的OP信息(更改所有F2的数量)
awk -F '[^[:digit:]]*' '
FNR==NR{n[$1]=$2;next}
{ for ( i=1; i<NF; i++) sub( $i, n[$i]) }
7
' File-2.txt File-1.txt
答案 2 :(得分:1)
我将假设文件未排序,即 File-1.txt 中的 m 行与文件中的 n 行匹配-2.txt ,其中 m 可能不等于 n 。 (在撰写本文时,您尚未提及文件是否已排序。)
解决此问题的一种方法是从 File-2.txt 构建哈希,逐行读取 File-1.txt ,并使用值替换值每行的哈希。
Perl中的示例
#!/usr/bin/perl
use strict;
use warnings;
my $filename1 = 'File-1.txt';
my $filename2 = 'File-2.txt';
my %hash;
my $fh;
open($fh, '<', $filename2) or die "Failed to open $filename2: $!";
while (<$fh>) {
chomp;
my ($key, $value) = split;
$hash{$key} = $value if $value;
}
close $fh;
open($fh, '<', $filename1) or die "Failed to open $filename1: $!";
while (<$fh>) {
s%^\(\K(\d+)%$hash{$1} // $1%e;
print;
}
close $fh;
示例输出
(0, ':', [])
(ALA_A_87, ':', [18])
(THR_A_127, ':', [20, 41])
(GLY_A_128, ':', [18])
(ILE_A_130, ':', [17])
(THR_A_166, ':', [])
(THR_A_167, ':', [])
...skipped...
(LEU_D_391, ':', [30])
(ASN_D_399, ':', [8])
(TYR_D_402, ':', [])
(SER_D_404, ':', [8])
(NAO1, ':', [])
如果您想替换所有数字,那就更容易了。替换此替换:
s%^\(\K(\d+)%$hash{$1} // $1%e;
用这个:
s%(\d+)%$hash{$1} // $1%ge;
示例输出
(0, ':', [])
(ALA_A_87, ':', [GLY_B_235])
(THR_A_127, ':', [CYS_B_237, SER_D_310])
(GLY_A_128, ':', [GLY_B_235])
(ILE_A_130, ':', [ASP_B_234])
(THR_A_166, ':', [])
...skipped...
(ARG_D_325, ':', [ASN_B_399, LEU_A_194, VAL_B_396])
(LEU_D_391, ':', [SER_B_310])
(ASN_D_399, ':', [GLY_A_190])
(TYR_D_402, ':', [])
(SER_D_404, ':', [GLY_A_190])
(NAO1, ':', [])
您也可以将此替换应用于整个文件内容。
注意,我使用%
作为正则表达式分隔符而不是通常的斜杠,因为否则在替换中不可能使用//
运算符。
注意,原始表达
s/^\((\d+)(.*)$/'(' . ( $hash{$1} || $1 ). $2/e;
不是最佳的,因为:
(.*)$
部分被不必要地处理; (
选项; \K
可能保持不变
由于使用 OR 运算符,表达式不太正确。如果$hash
中的密钥不存在,则$hash{$1}
为undef
。并且//
运算符更合适,因为只有在左侧操作数未定义时才返回右侧操作数。
答案 3 :(得分:1)
在Perl中
直接从%convert
的内容构建哈希File-2.txt
,并从其键构建正则表达式。然后它检查File-1.txt
的每一行是否有一对非空方括号,并将其中的所有数字转换为散列的相应值
use strict;
use warnings 'all';
use autodie;
my %convert = do {
open my $fh, '<', 'File-2.txt';
map { split } <$fh>;
};
my $re = join '|', keys %convert;
$re = qr/\b(?:$re)\b/;
open my $fh, '<', 'File-1.txt';
while ( <$fh> ) {
s/($re)/$convert{$1}/g;
print;
}
(0, ':', [])
(ALA_A_87, ':', [GLY_B_235])
(THR_A_127, ':', [CYS_B_237, SER_D_310])
(GLY_A_128, ':', [GLY_B_235])
(ILE_A_130, ':', [ASP_B_234])
(THR_A_166, ':', [])
(THR_A_167, ':', [])
(LYS_A_189, ':', [])
(GLY_A_190, ':', [LEU_D_391])
(ALA_A_191, ':', [])
(GLY_A_192, ':', [ARG_B_304])
(MET_A_193, ':', [ASP_B_241])
(LEU_A_194, ':', [])
(THR_B_200, ':', [SER_B_404])
(MET_B_201, ':', [])
(ASP_B_232, ':', [ASP_D_234])
(ILE_B_233, ':', [ASN_B_399])
(ASP_B_234, ':', [THR_B_200])
(GLY_B_235, ':', [])
(SER_B_236, ':', [])
(CYS_B_237, ':', [LEU_D_311])
(SER_B_238, ':', [GLN_B_305, ASN_B_240])
(ASN_B_240, ':', [GLY_B_235, MET_A_193, GLN_B_305, ARG_B_304])
(ASP_B_241, ':', [GLU_B_398])
(ALA_B_279, ':', [])
(GLU_B_280, ':', [])
(ARG_B_304, ':', [ASP_B_241, GLY_A_128])
(GLN_B_305, ':', [MET_A_193, VAL_B_396])
(ARG_B_308, ':', [ASN_D_399])
(ASP_B_309, ':', [THR_A_167])
(SER_B_310, ':', [])
(LYS_B_313, ':', [SER_B_238])
(LEU_B_391, ':', [ARG_B_308])
(TYR_B_395, ':', [MET_A_193, ARG_D_325, GLU_B_398, GLN_B_305])
(VAL_B_396, ':', [])
(GLU_B_398, ':', [ASP_B_309])
(ASN_B_399, ':', [LYS_A_189])
(SER_B_404, ':', [ARG_B_308])
(GLY_C_192, ':', [])
(ASP_D_234, ':', [ASP_B_309, LEU_D_391])
(ASP_D_309, ':', [])
(SER_D_310, ':', [ARG_D_325, LYS_A_189])
(LEU_D_311, ':', [THR_D_314])
(THR_D_314, ':', [ASN_B_240, GLY_B_235])
(ARG_D_325, ':', [ASN_B_399, LEU_A_194, VAL_B_396])
(LEU_D_391, ':', [SER_B_310])
(ASN_D_399, ':', [GLY_A_190])
(TYR_D_402, ':', [])
(SER_D_404, ':', [GLY_A_190])
(NAO1, ':', [])
答案 4 :(得分:0)
这个awk单行应该有所帮助:
awk 'NR==FNR{a[$1]=$2;next}{FS="[(,]"}sub(/[^,]*/,"("a[$2])+1' f2 f1
输出如下内容:
(, ':', [])
(ALA_A_87, ':', [18])
(THR_A_127, ':', [20, 41])
(GLY_A_128, ':', [18])
(ILE_A_130, ':', [17])
(THR_A_166, ':', [])
(THR_A_167, ':', [])
(LYS_A_189, ':', [])
(GLY_A_190, ':', [45])
(ALA_A_191, ':', [])
(GLY_A_192, ':', [26])
(MET_A_193, ':', [23])
(LEU_A_194, ':', [])
(THR_B_200, ':', [37])
.....
注意第一行,0
不存在于file2中,因此()
中有空,如果这不是您想要的,请让我知道应该有什么价值。
答案 5 :(得分:0)
这可能适合你(GNU sed):
sed -r 's/^(\S+)\s+(\S+)$/s:\\b\1\\b:\2:g/' file2 | sed -rf - file1
这会将文件2转换为sed脚本,作为文件1的查找。