【问题标题】:How do I get perl to print n lines following a specific string?如何让 perl 在特定字符串之后打印 n 行?
【发布时间】:2015-05-14 00:04:53
【问题描述】:

我有一个非常大的文件,想要提取平衡几何的所有原子符号和坐标。所需信息显示如下:

       ***** EQUILIBRIUM GEOMETRY LOCATED *****  
COORDINATES OF ALL ATOMS ARE (ANGS)    
       ATOM CHARGE     X              Y              Z     
-----------------------------------------------------------  
C           6.0   0.8438492825  -2.0554543742   0.8601734285  
C           6.0   1.7887997955  -1.2651150894   0.4121141006  
N           7.0   1.3006136046   0.0934593194   0.2602148346

注意:坐标完成后有一个空行。

到目前为止,我已经将一个对我有意义的代码拼凑在一起,但是它会产生错误,我不知道为什么。 它在调用脚本后需要一个文件,保存每一行并在看到包含触发符号和坐标记录的 EQUILIBRIUM GEOMETRY 的字符串时更改为 $start==1。它继续保存包含坐标格式的行,直到它看到一个空白行,它完成了记录到 $geom 中。

#!/usr/bin/perl

$num_args = $#ARGV + 1;
if ($num_args != 1) {
   print "\nMust supply GAMESS .log file.\n";
   exit;
}

$file = $ARGV[0];
open FILE, "<", $file;

$start = 0;
$geom="";
    
while (<FILE>) {
 $line = $_;
  if ( $line eq "\n" && ($start == 1) ) {
       $start = 0; }

 if ( $start == 1 && $line =~ m/\s+[A-Z]+\s+[0-9\.]+\s+[0-9\.\-]+\s+[0-9\.\-]+\s+[0-9\.\-]+/ ) {
$line =~ s/^\s+//;
@coordinates = split(/\s+/,$line);
$geom=$coordinates[0],$coordinates[3],$coordinates[4],$coordinates[5];

 }
 if ( $line =~ m/\s+\*+ EQUILIBRIUM GEOMETRY LOCATED\s\*+\s+) {
   $geom = "";
   $start = 1;
 }
}

print $geom; 

错误信息: Unrecognized character \xC2; marked by &lt;-- HERE after &lt;-- HERE near column 1 at ./perl-grep line 5.

【问题讨论】:

  • 如果包含错误,这个问题会更容易理解
  • 我看不出你为什么不在这里use strictuse warnings。如果您这样做,并收到任何错误消息/警告,请将它们包括在内。也许有人可以提供帮助。您的错误很可能出现在if 的第一个分支$geom =
  • Unrecognized character \xC2; marked by &lt;-- HERE after &lt;-- HERE near column 1 at ./perl-grep line 5.

标签: regex perl grep


【解决方案1】:

第 13 行有一个隐形字符

我创建了一个只有这一行的文件(通过剪切/粘贴) 然后在上面添加一行是我的重新输入

$geom="";

$geom="";

看起来一样,但实际上不是(第二行是有问题的)

[tmp]=> cat x | perl -ne '$LINE = $_; $HEX = unpack "H*"; print "$HEX $LINE" '
2467656f6d3d22223b0a $geom="";
2467656f6d3d22223be280a80a $geom="";

当您对文件进行六边形检查时,您会看到更多字符。 所以 => 只需完全删除这一行并重新输入

顺便说一句,你的文件中还有一个问题,你错过了关闭正则表达式'/'

if ( $line =~ m/\s+\*+ EQUILIBRIUM GEOMETRY LOCATED\s\*+\s+) {

但我想,完成你的脚本还有很多工作要做,因为我看不到太多目的;)

【讨论】:

    【解决方案2】:

    我把它复制到我的 Linux 机器上,遇到了同样的问题。

    基本上,脚本是说该行有一个不可读的字符:

    $geom="";
    

    我在 gedit 中重新输入了该行并运行了文件。

    此外,脚本底部还有一个未封闭的正则表达式。我在以下行中添加了一个“/”:

    if ( $line =~ m/\s+\*+ EQUILIBRIUM GEOMETRY LOCATED\s\*+\s+) {
    

    【讨论】:

      【解决方案3】:

      好的,首先 - strictwarnings 确实是您编写脚本并遇到问题时的第一个呼叫端口。实际上,即使在您遇到问题之前 - 打开它们并坚持它们*。

      与您的代码一样:

      • $geom="";? - 尾随问号。应该删除。
      • $num_args = $#ARGV + 1; - 多余的。 scalar @ARGV 具有相同的结果。
      • open FILE, "&lt;", $file; - 3 arg 打开很好。不使用词法文件句柄或检查成功是不好的。
      • $line = $_; - 多余的。只需改用while ( my $line = &lt;FH&gt; ) {
      • if ( $line =~ m/\s+\*+ EQUILIBRIUM GEOMETRY LOCATED\s\*+\s+) - 损坏的正则表达式,没有尾随 /
      • $geom=$coordinates[0],$coordinates[3],$coordinates[4],$coordinates[5]; - 不按照你的想法做。您可能想要join 这些或连接它们。
      • $line eq "\n" - 选择空白行,但如果你先 chomp;eq '' 可能会更好。
      • $start 看起来您正在尝试做与 range 运算符相同的事情。 http://perldoc.perl.org/perlop.html#Range-Operators
      • 你会覆盖$geom。这是你的意图吗?
      • $line =~ s/^\s+//; - 是多余的,因为你所做的只是splitsplit ' ' 做同样的事情。
      • 使用后close 你的文件句柄很好。特别是当它不是词法范围时。

      因此,考虑到这一点,您的代码可能看起来像这样:

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      if ( @ARGV != 1 and not -f $ARGV[0] ) {
          print "\nMust supply GAMESS .log file.\n";
          exit;
      }
      
      open( my $input_fh, "<", $ARGV[0] ) or die $!;
      
      my $geom = "";
      while ( my $line = <$input_fh> ) {
          chomp $line;
          if ( $line =~ m/\s+\*+ EQUILIBRIUM GEOMETRY LOCATED\s\*+\s+/ .. m/^$/ ) {
              if ( $line
                  =~ m/\s+[A-Z]+\s+[0-9\.]+\s+[0-9\.\-]+\s+[0-9\.\-]+\s+[0-9\.\-]+/
                  )
              {
                  my @coordinates = split( ' ', $line );
                  $geom = join( "",
                      $coordinates[0], $coordinates[3],
                      $coordinates[4], $coordinates[5] );
      
              }
          }
      }
      close($input_fh);
      print $geom;
      

      (如果您有一些示例输入,我会验证它)。

      * 有时您可能希望将其关闭。如果您知道这些是什么以及为什么,那么您将它们关闭。否则只是假设它们是强制性的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-16
        • 1970-01-01
        • 2020-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多