分离矢量场

时间:2015-09-01 13:13:53

标签: regex perl

我正在写一个perl脚本..我是perl的新手。这是我的代码

use warnings;
use strict;

my $file = $ARGV[0] ;
my $file2 = 'output.txt';

open FH, $file or die $!;
open FHH, "> $file2" or die $!;

while(<FH>) {
    if(/SIB_DBG/) {
        my $val = $_;
        if($val = /TTRB:([\da-f]+)/) {
            print "$1 \n";
        }
    }
}

这是输入文件的一行

Aug 31 15:25:53 usb3 kernel: [   78.813721] SIB_DBG TTRB:00000000 00000000 00000000 00001021, PTR: ffff88005ff8b850

我能够在TTRB之后立即分离8字节的第一个字段。但是之后如何将三个字段分开?

3 个答案:

答案 0 :(得分:2)

你遇到的问题是微不足道的,因为重复正则表达式会从字符串中提取更多数据。不过,我还有其他一些要点可以分享。

  • 您应该始终使用显式模式的open的三个参数版本,并使用词法文件句柄。例如:open my $fh, "<", $file or die $!
  • 您不需要显式打开文件,您可以使用菱形运算符,它将自动读取输入。这是在Perl中执行此操作的惯用方法。例如。 while (<>) { ... }。在命令行中,这是-n-p开关的作用。
  • 同样,只需打印到stdout并重定向终端中的输出,而不是打开输出文件。例如。 perl foo.pl input.txt > output.txt

还要注意代码的这一部分:

    if($val = /TTRB:([\da-f]+)/) {

当您打算使用绑定运算符=时,您正在使用赋值运算符=~。结果是,$val的内容不是$_,而是$val的内容。然后将该检查的返回值分配给 if($val = $_ =~ /TTRB:([\da-f]+)/) { 。它与写作相同

$_

因为没有绑定运算符的正则表达式匹配总是默认检查use strict; use warnings; while(<>) { if (/SIB_DBG/) { if (/TTRB:((?:[\da-f]+\s*)+)/) { print "$1 \n"; } } }

perl -nle 'print /SIB_DBG\s+TTRB:((?:[\da-f]+\s*)+)/' input.txt > output.txt

这将简单地匹配重复的字母数字序列并打印它们。你应该注意到这可以简化很多,直到最基本的单行:

print

正则表达式的匹配将返回-l,直接打印,synchronized (NThread.baton)开关将添加换行符。

答案 1 :(得分:1)

您可以在标量上下文中使用Perl全局正则表达式匹配(使用/g修饰符)。这使匹配只找到模式的 next 出现,因此您可以逐步处理字符串

该程序首先检查它是否可以在字符串中找到TTRB:,如果没有则跳过它。但是当它找到字符串时,它会在TTRB:之后留下一个特定于该字符串的内部指针,以便下一个全局匹配将从那里开始查看

然后它找到所有出现的八个十六进制数字,可能后跟一些空格。 \G锚点强制每个匹配开始与前一个匹配结束的位置完全相同,因此当它到达00001021后面跟一个逗号时,下一个搜索将失败,因为该模式要求接下来的八个数字开始逗号在哪里

我仅使用Data::Dump在操作后显示@data的内容

use strict;
use warnings;

use Data::Dump;

while ( <DATA> ) {
    next unless /TTRB:/g;

    my @data = /\G(\p{hex}{8})\s*/g;
    dd \@data;
}

__DATA__
Aug 31 15:25:53 usb3 kernel: [   78.813721] SIB_DBG TTRB:00000000 00000000 00000000 00001021, PTR: ffff88005ff8b850

输出

["00000000", "00000000", "00000000", "00001021"]

答案 2 :(得分:0)

试试这个:

    if($val =~ /TTRB:([\da-f]+)\s([\da-f]+)\s([\da-f]+)\s([\da-f]+)/)
    {
        print "$1 $2 $3 $4\n";
    }

$ 1包含前8个字节 $ 2包含第二个8字节,依此类推