0

我想编写一个特定的正则表达式来以特定的文件格式执行以下操作。

它应该能够使用正则表达式检查第三个字段是否只是一个 O 或在 O 之后有任何内容。

目前,我使用以下语法,如下所示:

   if ($line !~ /^ATOM\s+\d+\s+(O)/)
   {

   }

你们能帮帮我吗?

  ATOM     284  OD1  ASN 1   34   -7.92000  -6.74600  -4.73800 O_2    1 2 -0.55000 0   0
  ATOM     308  O    LEU 1   35  -10.48500 -13.59200  -8.35100 O_2    1 2 -0.51000 0   0

我希望能够从包含 O 之后的文件中打印出行(例如 OD1 行)。我应该可以只用一个 O 来删除这些线条。

4

4 回答 4

1

只需添加\S(意思是“非空格字符”):

/^ATOM\s+\d+\s+O\S/

顺便说一句,我的印象是您实际上并不知道正则表达式?我推荐perlretut“Perl 正则表达式教程”)手册页

于 2013-08-06T21:39:06.437 回答
0

您当前使用!~的 for 不匹配。如果您希望它匹配,则必须将其更改为=~. 你也不需要括号是O. ()用于捕获组。如果您想捕获该组,则可以执行 (O[A-Za-z0-9])。

if ($line =~ /^ATOM\s+\d+\s+O/)
# we don't care what's after the O, could be nothing or some characters

或者

if ($line =~ /^ATOM\s+\d+\s+(O[a-zA-Z0-9]*)/)
# this will capture OD1 or just O in $1

或者如果你想查看0之后是否有字符,你可以使用

if ($line =~ /^ATOM\s+\d+\s+(O[a-zA-Z0-9]+)/)
# this would only capture OD1 in $1
于 2013-08-06T21:41:41.307 回答
0

您可以使用split来拆分该字段:

 my $field = ( split /\s+/, $line )[2];

这将使正则表达式更容易你想要更容易做。另外,它使您正在做的事情更加明显:

 if ( $field =~ /^O/ ) {
     here be dragons...
 }

事实上,您可能希望对所有字段都这样做,以使其更易于操作。由于我不知道您的字段是什么意思,所以我只是称它们$fld1为 ,$fld2等。

my ( $fld1, $fld2, $fld3, $fld4, ... ) = split /\s+/, $line;
if ( $fld3 =~ /^O/ ) {
    here be dragons...
}

现在,您可以轻松地在程序中引用您的各个字段。

于 2013-08-06T22:42:16.750 回答
0

如果你不想使用正则表达式,你可以使用 @David-W 所说的 split

my @fields = split /\s+/, $line;
##now $field[2]
if ($fields[2] ne 'o'){
    ##this line has o and other letters
}

但这将比正则表达式慢得多,尤其是对于大型数据文件

至于正则表达式,您的数据文件以空格开头(显然),因此您的正则表达式应如下所示

if ($line !~ /^\s+ATOM\s+\d+\s+(O)\s+/){
    ##this line has o with other letters beside it
} else {
    ## this line only has o in field 3
}

在开头添加 ^\s+ 或完全删除 ^ 标记

$line !~ /ATOM\s+\d+\s+(O)\s+/

然后在 o (最后)之后添加 \s+ 以确保它紧跟空格

如果您对捕获字段值不感兴趣,则最好捕获组(o)

if ($line !~ /ATOM\s+\d+\s+O\s+/) {
    #...
} else {
    #...
}
于 2013-08-06T22:57:53.823 回答