我想阅读看起来像我的mol2文件:
@MOLECULE 19020135 20 21 0 0 0 SMALL GASTEIGER @ATOM 1 N 1.784 1.464 1.547 N.3 1 LIG1 2 O 1.657 6.176 1.764 O.3 1 LIG1 3 C 1.836 2.748 6.867 C.ar 1 LIG1 4 C 1.873 3.678 3.893 C.3 1 LIG1
我希望输出:
1 N 1.784 1.464 1.547 2 O 1.657 6.176 1.764 3 C 1.836 2.748 6.867 4 C 1.873 3.678 3.893
我正在使用这个正则表达式
=~/\s+\d+\s+(\w+)\s+(\S+\.\S+)\s+(\S+\.\S+)\s+(\S+\.\S+)\s+(\w{1})\s+.+\s+/ig)
请帮助我阅读我的文件,以便获得所需的输出
答案 0 :(得分:2)
假设@WORD
是此处的记录分隔符,您可以通过设置输入记录分隔符$/
来逐个读取记录。然后你可以用替换删除最后3列并打印它们。
/m
修饰符允许$
匹配多行字符串中的换行符。
use strict;
use warnings;
$/ = '@';
while (<DATA>) {
chomp; # remove @ from end
if (s/^ATOM\n//) {
s/(?:\s+\S+){3}$//gm;
print;
}
}
__DATA__
@MOLECULE
19020135
20 21 0 0 0
SMALL
GASTEIGER
@ATOM
1 N 1.784 1.464 1.547 N.3 1 LIG1
2 O 1.657 6.176 1.764 O.3 1 LIG1
3 C 1.836 2.748 6.867 C.ar 1 LIG1
4 C 1.873 3.678 3.893 C.3 1 LIG1
<强>输出:强>
1 N 1.784 1.464 1.547
2 O 1.657 6.176 1.764
3 C 1.836 2.748 6.867
4 C 1.873 3.678 3.893
<强>用法:强>
将<DATA>
更改为<>
,然后:
perl script.pl input.txt > output.txt
重定向到输出文件是可选的。
更新:您还可以使用"flip-flop"来确定记录的边框,这可能是更好的解决方案。在这种情况下,您不需要/gm
修饰符。
while (<DATA>) {
if (/^\@ATOM$/ ... /^\@/) { # the "flip-flop"
next if /^\@/;
s/(?:\s+\S+){3}$//;
print;
}
}
答案 1 :(得分:1)
我知道这是标记perl
但这里是awk
解决方案(不保留原始空格)。这甚至适用于多个记录,其中@ATOM
用作记录分隔符,因为您的输入文件格式不完全清楚:
$ awk '/^@ATOM/,/^@ATOM/{t=1; next} t && NF>1{print $1,$2,$3,$4,$5}' test.txt
1 N 1.784 1.464 1.547
2 O 1.657 6.176 1.764
3 C 1.836 2.748 6.867
4 C 1.873 3.678 3.893
答案 2 :(得分:0)
你可以这样做:
#!/usr/bin/perl
use strict;
use warnings;
while(<DATA>) {
if ($_ =~ /(\d+\h+[A-Z][a-z]?\d*\h+(?: -?[\d.]+){3})/) {
print $1 . "\n";
}
}
__DATA__
@MOLECULE
19020135
20 21 0 0 0
SMALL
GASTEIGER
@ATOM
1 N 1.784 1.464 1.547 N.3 1 LIG1
2 O 1.657 6.176 1.764 O.3 1 LIG1
3 C 1.836 2.748 6.867 C.ar 1 LIG1
4 C 1.873 3.678 3.893 C.3 1 LIG1