Perl 使用另一个文件而不使用循环重命名文件中的名称
我有两个文件: one.txt看起来像这样:Perl 使用另一个文件而不使用循环重命名文件中的名称,perl,matlab,sed,awk,grep,Perl,Matlab,Sed,Awk,Grep,我有两个文件: one.txt看起来像这样: >ENST001 (((....))) (((...))) >ENST002 (((((((.......)))))) ((((...))) 我还有一万个 two.txt如下所示: >ENST001 110 >ENST002 59 >ENST001_110 (((....))) (((...))) >ENST002_59 (((((((.......)))))) ((((..
>ENST001
(((....)))
(((...)))
>ENST002
(((((((.......))))))
((((...)))
我还有一万个
two.txt如下所示:
>ENST001 110
>ENST002 59
>ENST001_110
(((....)))
(((...)))
>ENST002_59
(((((((.......))))))
((((...)))
#!/usr/bin/perl
open(FH1, "one.txt");
open(FH2, "two.txt");
open(RESULT, ">result.txt");
my %data;
while (my $line = <FH2>)
{
chomp(line);
# Delete leading angle bracket
$line =~ s/>//d;
# split enst and pos
my ($enst, $post) = split(/\s+/, line);
# Store POS with ENST as key
$data{$enst} = $pos;
}
close(FH2);
while (my $line = <FH1>)
{
# Check line for ENST
if ($line =~ m/^>(ENST\d+)/)
{
my $enst = $1;
# Get pos for ENST
my $pos = $data{$enst};
# make new line
$line = '>' . $enst . '_' . $pos . '\n';
}
print RESULT $line;
}
close(FH1);
close(RESULT);
其他所有的ENST都是如此
我基本上想用two.txt中两个字段的组合来替换one.txt中的ENSTs,因此结果如下所示:
>ENST001 110
>ENST002 59
>ENST001_110
(((....)))
(((...)))
>ENST002_59
(((((((.......))))))
((((...)))
#!/usr/bin/perl
open(FH1, "one.txt");
open(FH2, "two.txt");
open(RESULT, ">result.txt");
my %data;
while (my $line = <FH2>)
{
chomp(line);
# Delete leading angle bracket
$line =~ s/>//d;
# split enst and pos
my ($enst, $post) = split(/\s+/, line);
# Store POS with ENST as key
$data{$enst} = $pos;
}
close(FH2);
while (my $line = <FH1>)
{
# Check line for ENST
if ($line =~ m/^>(ENST\d+)/)
{
my $enst = $1;
# Get pos for ENST
my $pos = $data{$enst};
# make new line
$line = '>' . $enst . '_' . $pos . '\n';
}
print RESULT $line;
}
close(FH1);
close(RESULT);
我写了一个matlab脚本来实现这一点,但是由于它在two.txt中循环所有行,所以需要6个小时才能完成,所以我认为使用awk、sed、grep甚至perl,我们可以在几分钟内得到结果。这就是我在matlab中所做的:
frf = fopen('one.txt', 'r');
frp = fopen('two.txt', 'r');
fw = fopen('result.txt', 'w');
while feof(frf) == 0
line = fgetl(frf);
first_char = line(1);
if strcmp(first_char, '>') == 1 % if the line in one.txt start by > it is the ID
id_fold = strrep(line, '>', ''); % Reomve the > symbol
frewind(frp) % Rewind two.txt file after each loop
while feof(frp) == 0
raw = fgetl(frp);
scan = textscan(raw, '%s%s');
id_pos = scan{1}{1};
pos = scan{2}{1};
if strcmp(id_fold, id_pos) == 1 % if both ids are the same
id_new = ['>', id_fold, '_', pos];
fprintf(fw, '%s\n', id_new);
end
end
else
fprintf(fw, '%s\n', line); % if the line doesn't start by > print it to results
end
结束使用sed,您首先只能在two.txt上运行。您可以根据需要制作一个sed命令进行替换,然后在one.txt上运行:
第一条路
第二条路
若文件很大,你们会得到太多的参数,和前面的方法错误。因此,有另一种方法来修复此错误。您需要逐个执行所有三个命令:
sed -n '1i#!/bin/sed -f
/>ENST/{s=.*\(ENST[0-9]\+\)\s\+\([0-9]\+\).*=s/\1/\1_\2/;=;p}' two.txt > script.sed
chmod +x script.sed
./script.sed one.txt
第一个命令将形成sed脚本,可以根据需要修改一个.txt。chmod将使这个新脚本可执行。最后一个命令将执行该命令。因此每个文件只读取一次。没有任何循环。
请注意,第一个命令由两行组成,但仍然是一个命令。如果删除换行符,将中断脚本。这是因为我在sed中的命令。您可以在“sed手册页”中查找详细信息。使用sed,您首先只能在two.txt上运行。您可以根据需要制作一个sed命令来替换它,然后在one.txt上运行它:
第一条路
第二条路
若文件很大,你们会得到太多的参数,和前面的方法错误。因此,有另一种方法来修复此错误。您需要逐个执行所有三个命令:
sed -n '1i#!/bin/sed -f
/>ENST/{s=.*\(ENST[0-9]\+\)\s\+\([0-9]\+\).*=s/\1/\1_\2/;=;p}' two.txt > script.sed
chmod +x script.sed
./script.sed one.txt
第一个命令将形成sed脚本,可以根据需要修改一个.txt。chmod将使这个新脚本可执行。最后一个命令将执行该命令。因此每个文件只读取一次。没有任何循环。
请注意,第一个命令由两行组成,但仍然是一个命令。如果删除换行符,将中断脚本。这是因为我在sed中的命令。您可以在“sed手册页”中查找详细信息。使用awk的单向方式。FNR==NR处理参数中的第一个文件并保存每个数字。第二个条件处理第二个文件,当第一个字段与数组中的键匹配时,会修改追加数字的行
awk '
FNR == NR {
data[ $1 ] = $2;
next
}
FNR < NR && data[ $1 ] {
$0 = $1 "_" data[ $1 ]
}
{ print }
' two.txt one.txt
单向使用awk。FNR==NR处理参数中的第一个文件并保存每个数字。第二个条件处理第二个文件,当第一个字段与数组中的键匹配时,会修改追加数字的行
awk '
FNR == NR {
data[ $1 ] = $2;
next
}
FNR < NR && data[ $1 ] {
$0 = $1 "_" data[ $1 ]
}
{ print }
' two.txt one.txt
把问题迎头解决。在perl中,我将执行以下操作:
>ENST001 110
>ENST002 59
>ENST001_110
(((....)))
(((...)))
>ENST002_59
(((((((.......))))))
((((...)))
#!/usr/bin/perl
open(FH1, "one.txt");
open(FH2, "two.txt");
open(RESULT, ">result.txt");
my %data;
while (my $line = <FH2>)
{
chomp(line);
# Delete leading angle bracket
$line =~ s/>//d;
# split enst and pos
my ($enst, $post) = split(/\s+/, line);
# Store POS with ENST as key
$data{$enst} = $pos;
}
close(FH2);
while (my $line = <FH1>)
{
# Check line for ENST
if ($line =~ m/^>(ENST\d+)/)
{
my $enst = $1;
# Get pos for ENST
my $pos = $data{$enst};
# make new line
$line = '>' . $enst . '_' . $pos . '\n';
}
print RESULT $line;
}
close(FH1);
close(RESULT);
把问题迎头解决。在perl中,我将执行以下操作:
>ENST001 110
>ENST002 59
>ENST001_110
(((....)))
(((...)))
>ENST002_59
(((((((.......))))))
((((...)))
#!/usr/bin/perl
open(FH1, "one.txt");
open(FH2, "two.txt");
open(RESULT, ">result.txt");
my %data;
while (my $line = <FH2>)
{
chomp(line);
# Delete leading angle bracket
$line =~ s/>//d;
# split enst and pos
my ($enst, $post) = split(/\s+/, line);
# Store POS with ENST as key
$data{$enst} = $pos;
}
close(FH2);
while (my $line = <FH1>)
{
# Check line for ENST
if ($line =~ m/^>(ENST\d+)/)
{
my $enst = $1;
# Get pos for ENST
my $pos = $data{$enst};
# make new line
$line = '>' . $enst . '_' . $pos . '\n';
}
print RESULT $line;
}
close(FH1);
close(RESULT);
这可能适用于GNU sed:
sed -n '/^$/!s|^\(\S*\)\s*\(\S*\).*|s/^\1.*/\1_\2/|p' two.txt | sed -f - one.txt
这可能适用于GNU sed:
sed -n '/^$/!s|^\(\S*\)\s*\(\S*\).*|s/^\1.*/\1_\2/|p' two.txt | sed -f - one.txt
这个Perl解决方案将修改后的one.txt文件发送到STDOUT
这个Perl解决方案将修改后的one.txt文件发送到STDOUT
尝试此MATLAB解决方案无循环:
%# read files as cell array of lines
fid = fopen('one.txt','rt');
C = textscan(fid, '%s', 'Delimiter','\n');
C1 = C{1};
fclose(fid);
fid = fopen('two.txt','rt');
C = textscan(fid, '%s', 'Delimiter','\n');
C2 = C{1};
fclose(fid);
%# use regexp to extract ENST numbers from both files
num = regexp(C1, '>ENST(\d+)', 'tokens', 'once');
idx1 = find(~cellfun(@isempty, num)); %# location of >ENST line
val1 = str2double([num{:}]); %# ENST numbers
num = regexp(C2, '>ENST(\d+)', 'tokens', 'once');
idx2 = find(~cellfun(@isempty, num));
val2 = str2double([num{:}]);
%# construct new header lines from file2
C2(idx2) = regexprep(C2(idx2), ' +','_');
%# replace headers lines in file1 with the new headers
[tf,loc] = ismember(val2,val1);
C1( idx1(loc(tf)) ) = C2( idx2(tf) );
%# write result
fid = fopen('three.txt','wt');
fprintf(fid, '%s\n',C1{:});
fclose(fid);
尝试此MATLAB解决方案无循环:
%# read files as cell array of lines
fid = fopen('one.txt','rt');
C = textscan(fid, '%s', 'Delimiter','\n');
C1 = C{1};
fclose(fid);
fid = fopen('two.txt','rt');
C = textscan(fid, '%s', 'Delimiter','\n');
C2 = C{1};
fclose(fid);
%# use regexp to extract ENST numbers from both files
num = regexp(C1, '>ENST(\d+)', 'tokens', 'once');
idx1 = find(~cellfun(@isempty, num)); %# location of >ENST line
val1 = str2double([num{:}]); %# ENST numbers
num = regexp(C2, '>ENST(\d+)', 'tokens', 'once');
idx2 = find(~cellfun(@isempty, num));
val2 = str2double([num{:}]);
%# construct new header lines from file2
C2(idx2) = regexprep(C2(idx2), ' +','_');
%# replace headers lines in file1 with the new headers
[tf,loc] = ismember(val2,val1);
C1( idx1(loc(tf)) ) = C2( idx2(tf) );
%# write result
fid = fopen('three.txt','wt');
fprintf(fid, '%s\n',C1{:});
fclose(fid);
是的,这就是为什么我写了关于通过文件运行的第二部分答案。试试看,它应该很好用。注意,在-f之后必须有换行符。否则它将无法正常工作。第二部分中的文件one.txt是missdNope。事实并非如此。好的,我已经更新了我的帖子,让它更清晰一些。是的,这就是为什么我在回答的第二部分写了关于通过文件运行的内容。试试看,它应该很好用。注意,在-f之后必须有换行符。否则它将无法正常工作。第二部分中的文件one.txt是missdNope。事实并非如此。好的,我已经更新了我的帖子,让它更清晰一点。你应该使用三参数版本的open和LexicalFileHandles。并始终使用严格的开始脚本;并使用警告;。您应该使用open和lexicalfilehandles的三参数版本。并始终使用严格的开始脚本;并使用警告;。