我正在编写一个脚本,它将读取包含Angstroms测量结果的文件,并将它们转换为nm(1埃= 0.1 nm)。
以下是一些示例,它应该找到并替换:
3A
12 A
2.75 angstroms
0.123 Angstroms
不应改变以下示例: 我喜欢数字3.一个非常好的数字。伦敦动物园里有27个Aardvarks。
这是我到目前为止所得到的。有两件事我有问题,我怎么能表现出来"以10"找到匹配后将其写回文件?我只是不知道正则表达式应该如何看待这个问题。
use strict;
use warnings;
my $filename = 'angstrom.txt';
open(FILE, $filename) or die "Can't open $filename: $!";
my @lines = <FILE>;
close(FILE);
open(FILE, ">$filename") or die "Can't write to $filename: $!";
foreach my $line (@lines) {
if($line =~ s/\d{2}\w//e)
{
print FILE (@lines);
}
}
close(FILE);
答案 0 :(得分:1)
正则表达式的问题在于 - 他们并不擅长理解&#39;一个数值。他们关于文字。
你可以在这种特定情况下做到这一点,因为你要除以10,但我通常不称它为好主意。
相反 - 提取要更改的值,并对其应用乘法:
s|([\d\.]+) angstroms|$1 / 10 . " nm"|eig;
这将捕获&#39;数字+小数&#39;在“埃”之前,除以10,然后加入“&#39; nm&#39;代替。
i
标志使匹配大小写不敏感。 e
标记表示评估&#39;替换为perl。 g
要做到这一点&#34;全球&#34;每行 - 根据您的示例数据,这可能无关紧要。 注意 - 我们还使用|
而不是更常见的/
分隔符,因为我们在表达式中使用/
。 (你可以逃脱它,但我认为这更清楚了)
为了对您的文件执行此操作,我们可以使用perlrun
标记-i
- 就地编辑。 (在指定扩展名之后 - 它将源重命名为该扩展名,然后重新编写该文件)
perl -i.bak -pe 's|([\d\.]+) angstroms|$1 / 10 . " nm"|eig' angstrom.txt
或者您可以将上述内容拼接到您的代码中。
我通常会建议避免读写&#39;这样的操作,因为它确实意味着代码故障意味着您丢失了源数据。打开一个新的输出文件,然后写入它 - 然后在完成(成功)后重命名它是一种更好的做法。
(它还消耗与源文件成比例的内存。这通常不是问题,但有时可能变得相关)。
鉴于您的代码需要匹配A,Angstrom或Angstroms(我假设您没有&#39; amps&#39;担心?)
perl -i.bak -pe 's|([\d\.]+)\s*a(?:ngstroms)?\b|$1 / 10 . " nm"|ei' angstrom.txt
这是匹配a
,A
,angstroms
或Anstroms
的额外步骤,我们\b
要求立即断言。所以&#34; 12苹果&#34;不会抓住我们。
也许具有讽刺意味的是 - -i.bak -pe
实际上可能比写出它更容易。但是如果你想要:
#!/usr/bin/perl
use strict;
use warnings;
my $filename = 'angstrom.txt';
open(my $input, '<', $filename) or die "Can't open $filename: $!";
open(my $output, '>', $filename.".new" ) or die $!;
select $output;
while ( <$input> ) {
s|([\d\.]+)\s*a(?:ngstroms)?\b|$1 / 10 . " nm"|eig;
print;
}
close ( $input );
close ( $output );
#rename .new here