在这里得到一些帮助之后我就想到了(我希望通过尝试将多个脚本放在一起来学习)。下面的脚本将执行HW和OW替换,但不运行if语句。
*#*!/usr/bin/perl
use strict;
use warnings 'all';
$^I = '.bak'; # create a backup copy
while (<>) {
s/HW/HT/g; # do the replacement of HW with HT
s/OW/OT/g; # do a second replacement OW with OT
*#* Hopefully run the if statement
my @parts = /\s*\S+/g;
if ( $parts[1] =~ s/([HO])W/$1T/ ) {
$parts[5] = sprintf '%*d',
length $parts[5],
$parts[1] =~ /HT/ ? 2002 : 2001;
}
print @parts, "\n";
}
如果人们遇到类似的问题,我已将其余部分留在下面。
我想通过在字符串开头搜索特定字母来使用Perl替换文件中的文本。例如,这是文件的一部分:
6 HT 4.092000 4.750000 -0.502000 0 5 7
7 HT 5.367000 5.548000 -0.325000 0 5 6
8 OT -5.470000 5.461000 1.463000 0 9 10
9 HT -5.167000 4.571000 1.284000 0 8 10
10 HT -4.726000 6.018000 1.235000 0 8 9
11 OT -4.865000 -5.029000 -3.915000 0 12 13
12 HT -4.758000 -4.129000 -3.608000 0 11 13
我想使用HT
作为搜索,并且可以使用2002
替换零列中的“0”。我知道如何替换整列零,但我不知道如何使其特定于行。在使用HT作为搜索后,我需要搜索OT
并将0
列替换为2001
。
基本上我需要搜索一个标识该行的字符串,并替换该行的特定字符串,而其间的文本是可变的。输出需要打印到new_file.xyz。我也会在很多文件上反复这样做。 谢谢你的帮助。
这是我正在使用的python代码,但无法弄清楚如何使“file.txt”成为接受命令后键入的文件的变量。此代码要求我每次使用时都将“file.txt”更改为文件的名称。我也无法打印到新文件。
python代码:
#!/usr/bin/python
with open('file.txt') as f:
lines = f.readlines()
new_lines = []
for line in lines:
if "HT" in line:
new_line = line.replace(' 0 ', '2002')
new_lines.append(new_line)
else:
new_lines.append(line)
content = ''.join(new_lines)
print(content)
我已经能够在Perl中完成一些工作,并希望有一个脚本可以按顺序执行所有替换步骤,因为所有HT
都以{{1}开头并且所有HW
都以OT
开头。
Perl脚本:
OW
感谢您的帮助。
哦,我很遗憾仅限于Python 2.7,因为有人建议使用python 3.0的代码。我纯粹是大学集群的用户,但会询问有关升级python的问题。
答案 0 :(得分:2)
所以 想要做的就是在第二列中将所有HW
更改为HT
并将OW
更改为OT
,并且如果为OW
,则将第6列更改为2001,将HW
更改为2002?
看起来像这样
use strict;
use warnings 'all';
while ( <DATA> ) {
my @parts = /\s*\S+/g;
if ( $parts[1] =~ s/([HO])W/$1T/ ) {
$parts[5] = sprintf '%*d',
length $parts[5],
$1 eq 'H' ? 2002 : 2001;
}
print @parts, "\n";
}
__DATA__
6 HW 4.092000 4.750000 -0.502000 0 5 7
7 HW 5.367000 5.548000 -0.325000 0 5 6
8 OW -5.470000 5.461000 1.463000 0 9 10
9 HW -5.167000 4.571000 1.284000 0 8 10
10 HW -4.726000 6.018000 1.235000 0 8 9
11 OW -4.865000 -5.029000 -3.915000 0 12 13
12 HW -4.758000 -4.129000 -3.608000 0 11 13
6 HT 4.092000 4.750000 -0.502000 2002 5 7
7 HT 5.367000 5.548000 -0.325000 2002 5 6
8 OT -5.470000 5.461000 1.463000 2001 9 10
9 HT -5.167000 4.571000 1.284000 2002 8 10
10 HT -4.726000 6.018000 1.235000 2002 8 9
11 OT -4.865000 -5.029000 -3.915000 2001 12 13
12 HT -4.758000 -4.129000 -3.608000 2002 11 13
如果它很重要,这个解决方案会注意保持每行中所有值的位置不变
通过检查第二个字段是否包含字符串HT
或OT
来选择要修改的行。鉴于您提供的小数据样本,我不知道这是否足够
这是出于演示目的。我相信您可以修改代码以在必要时打开外部文件,并从DATA
use strict;
use warnings 'all';
while ( <DATA> ) {
my @parts = /\s*\S+/g;
if ( $parts[1] =~ /[HO]T/ ) {
$parts[5] = sprintf '%*d',
length $parts[5],
$parts[1] =~ /HT/ ? 2002 : 2001;
}
print @parts, "\n";
}
__DATA__
6 HT 4.092000 4.750000 -0.502000 0 5 7
7 HT 5.367000 5.548000 -0.325000 0 5 6
8 OT -5.470000 5.461000 1.463000 0 9 10
9 HT -5.167000 4.571000 1.284000 0 8 10
10 HT -4.726000 6.018000 1.235000 0 8 9
11 OT -4.865000 -5.029000 -3.915000 0 12 13
12 HT -4.758000 -4.129000 -3.608000 0 11 13
6 HT 4.092000 4.750000 -0.502000 2002 5 7
7 HT 5.367000 5.548000 -0.325000 2002 5 6
8 OT -5.470000 5.461000 1.463000 2001 9 10
9 HT -5.167000 4.571000 1.284000 2002 8 10
10 HT -4.726000 6.018000 1.235000 2002 8 9
11 OT -4.865000 -5.029000 -3.915000 2001 12 13
12 HT -4.758000 -4.129000 -3.608000 2002 11 13
答案 1 :(得分:1)
看起来它使用固定宽度字段,所以
sub trim { $_[0] =~ s/^\s+//r =~ s/\s+\z//r }
while (<>) {
my $code = trim(substr($_, 2, 4));
if ($code eq "HW") {
substr($_, 2, 4, " HT");
substr($_, 43, 6, " 2002");
}
elsif ($code eq "OW") {
substr($_, 2, 4, " OT");
substr($_, 43, 6, " 2001");
}
print;
}
清洁剂:
sub parse {
my ( @format, @row );
while ($_[0] =~ /\G\s*(\S+)/g) {
push @row, $1;
push @format, '%'.( $+[0] - $-[0] ).'s';
}
return ( join('', @format)."\n", @row );
}
while (<>) {
my ($format, @row) = parse($_);
if ($row[1] eq "HW") { $row[1] = "HT"; $row[5] = 2002; }
elsif ($row[1] eq "OW") { $row[1] = "OT"; $row[5] = 2001; }
printf($format, @row);
}
答案 2 :(得分:0)
似乎您想使用正则表达式来执行字符串替换。 IMO,你应该在一次替换中完成所有操作,因为它不是更复杂,它可能更快,更不容易出错(因为更短)。
以下是我了解您的要求: 在你的行中,你有一个H或一个O,后跟一个你要强制为T的T或W,然后是你要复制的3个字段,然后是第4个字段。如果第4个字段为0,则需要根据字母H或O将其替换为2002或2001。
这给出了:
while (my $line = <>) {
$line =~ s/(\s*)([HO])(T|W)(\s+\S+\s+\S+\s+\S+)(\s+\d+)/$1.$2.'T'.$4.($5 == 0 ? ($2 eq 'H' ? ' 2002' : ' 2001') : $5)/eg;
print $line;
}