Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Perl中检查LF是否位于大标量末尾的最快方法?_Perl - Fatal编程技术网

在Perl中检查LF是否位于大标量末尾的最快方法?

在Perl中检查LF是否位于大标量末尾的最快方法?,perl,Perl,我想出了以下方法来检查换行符的$scaler的最终字符: if( $buffer !~ /\n$/ ) { if( substr( $buffer, -1, 1 ) !~ /\n/ ) { if( substr( $buffer, -1, 1 ) ne '\n' ) { 有没有更快的方法?$buffer标量的大小可能会变大,我注意到它越大,这些条件运行的时间就越长。我确实有另一个标量包含$buffer的长度,如果这有帮助的话 谢谢 完整代码: #!/usr/bin/perl use stric

我想出了以下方法来检查换行符的$scaler的最终字符:

if( $buffer !~ /\n$/ ) {
if( substr( $buffer, -1, 1 ) !~ /\n/ ) {
if( substr( $buffer, -1, 1 ) ne '\n' ) {
有没有更快的方法?$buffer标量的大小可能会变大,我注意到它越大,这些条件运行的时间就越长。我确实有另一个标量包含$buffer的长度,如果这有帮助的话

谢谢

完整代码:

#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw();
use Time::HiRes qw( gettimeofday tv_interval );

use constant BUFSIZE => 2 ** 21; # 2MB worked best for me, YMMV.

die "ERROR: Missing filename" if( !$ARGV[0] );

my $top = [gettimeofday];
sysopen( my $fh, $ARGV[0], Fcntl::O_RDONLY | Fcntl::O_BINARY ) or
  die "ERROR: Unable to open $ARGV[0], because $!\n";
open my $output, ">", "/dev/null";  # for 'dummy' processing

my $size = -s $ARGV[0];
my $osiz = $size;
my( $buffer, $offset, $lnCtr ) = ( "", "", 0 );
while( $size ) {
    my $read = sysread( $fh, $buffer, BUFSIZE, length($offset) );
    $size -= $read;
    my @lines = split /\n/, $buffer;
    if( substr( $buffer, -1, 1 ) ne "\n" ) {
        $offset = pop( @lines );
    } else {
        $offset = "";
    }
    for my $line ( @lines ) {
        processLine( \$line );
        $lnCtr++;
    }
    $buffer = $offset if( $offset );
}
close $fh;
print "Processed $lnCtr lines ($osiz bytes) in file: $ARGV[0] in ".
      tv_interval( $top ).
      " secs.\n";
print "Using a buffered read of ".BUFSIZE." bytes.  -  JLB\n";

sub processLine {
    if( ref($_[0]) ) {
        print $output ${$_[0]}."\n";
    } else {
        print $output $_[0]."\n";
    }
    return 0;
}
我想我已经达到了“收益递减点”,我试图让这个运行更快。它现在似乎能够以RAID5 SSD获取数据的速度读取数据。如您所见,我没有使用chomp()是有原因的,输入可以包含数十万个换行符,我需要保留这些换行符才能断开换行符进行处理。 ./fastread.pl newdata.log 在0.674738秒内处理了文件newdata.log中的516670行(106642635字节)。
使用2097152字节的缓冲读取。-JLB

我怀疑perl将字符串视为utf-8,出于某种原因,必须对整个字符串进行迭代

您可以暂时切换到字节语义,以查看末尾的字符是否为换行符

sub processLine {
   print $_[0] $_[1];
}


open(my $fh, '<:raw', $ARGV[0])
   or die("Can't open $ARGV[0]: $!\n");

my $buffer = '';
my $lnCtr = 0;
while (1) {
   my $rv = sysread($fh, $buffer, BUFSIZE, length($buffer));
   die $! if !defined($rv);
   last if !$rv;

   while ($buffer =~ s/(.*\n)//) {
      processLine($1);
      ++$lnCtr;
   }
}

if (length($buffer)) {
   processLine($output, $buffer);
   ++$lnCtr;
}

请参阅文档了解Perl和。

我怀疑Perl将字符串视为utf-8,并且出于某种原因必须对整个字符串进行迭代

您可以暂时切换到字节语义,以查看末尾的字符是否为换行符

sub processLine {
   print $_[0] $_[1];
}


open(my $fh, '<:raw', $ARGV[0])
   or die("Can't open $ARGV[0]: $!\n");

my $buffer = '';
my $lnCtr = 0;
while (1) {
   my $rv = sysread($fh, $buffer, BUFSIZE, length($buffer));
   die $! if !defined($rv);
   last if !$rv;

   while ($buffer =~ s/(.*\n)//) {
      processLine($1);
      ++$lnCtr;
   }
}

if (length($buffer)) {
   processLine($output, $buffer);
   ++$lnCtr;
}
请参阅文档了解Perl和。

您可以尝试。Chomp将返回从行尾删除的下线字符数:

if ( chomp $buffer ) {
    print "You had an LF on the end of \$buffer";
}
当然,chomp会删除它计数的NL字符。

您可以尝试。Chomp将返回从行尾删除的下线字符数:

if ( chomp $buffer ) {
    print "You had an LF on the end of \$buffer";
}

当然,chomp会删除它计数的NL字符。

你为什么担心速度?这段代码在您的程序中是不是有一部分相当慢,可能是用Devel::NYTProf描述的?如果没有,那么我建议你选择最清晰易读、最惯用的,可能是

if( $buffer !~ /\n$/ )
您的最终版本:

if( substr( $buffer, -1, 1 ) ne '\n' )
除了引用换行符之外,这也是一个不错的选择,这样可以得到一个由反斜杠和小写n组成的两个字符串。也许你来自C语言,其中单字符是单引号,字符串是双引号?你想要

if( substr( $buffer, -1, 1 ) ne "\n" )
这个版本

if( substr( $buffer, -1, 1 ) !~ /\n/ )

正在进行不应该的正则表达式匹配,因为它正在检查单字符字符串与单字符正则表达式。下一个阅读代码的人会认为这很奇怪,并想知道你为什么会这样做。另外,回到速度的问题上,将字符串与正则表达式进行匹配比仅与单个字符进行相等比较要慢。

为什么要担心速度?这段代码在您的程序中是不是有一部分相当慢,可能是用Devel::NYTProf描述的?如果没有,那么我建议你选择最清晰易读、最惯用的,可能是

if( $buffer !~ /\n$/ )
您的最终版本:

if( substr( $buffer, -1, 1 ) ne '\n' )
除了引用换行符之外,这也是一个不错的选择,这样可以得到一个由反斜杠和小写n组成的两个字符串。也许你来自C语言,其中单字符是单引号,字符串是双引号?你想要

if( substr( $buffer, -1, 1 ) ne "\n" )
这个版本

if( substr( $buffer, -1, 1 ) !~ /\n/ )

正在进行不应该的正则表达式匹配,因为它正在检查单字符字符串与单字符正则表达式。下一个阅读代码的人会认为这很奇怪,并想知道你为什么会这样做。另外,回到速度方面,将字符串与正则表达式进行匹配要比仅与单个字符进行相等比较慢。

Perl有两种字符串存储格式

其中一种格式使用相同数量的字节(1)来存储字符串可能包含的每个字符。正因为如此,而且Perl跟踪一个字符串使用了多少字节,因此
substr($x,-1)
在这种格式的字符串上的性能并不取决于字符串的长度

上述格式的问题是,它只能存储非常有限的字符范围。它可用于存储Unicode码点“Eric”和“êric”,但不能用于存储“ΕλΔα”。必要时(甚至不必要时),Perl将自动将字符串的存储格式切换为其他格式

第二种格式可以将任何Unicode代码点存储为字符。实际上,它可以存储任何32位或64位的值(取决于
perl
的构建设置)。缺点是使用可变字节数来存储每个字符。因此,即使Perl知道整个字符串使用的字节数,它也不知道第一个字符从哪里开始。*要查找最后一个字符,它必须扫描整个字符串

这就是说,由于存储格式的属性,实际上很容易在固定时间内找到字符串的最后一个字符

use Inline C => <<'__END_OF_C__';

   # O(1) version of substr($x,-1)
   SV* last_char(SV* sv) {
      STRLEN len;
      const char* s = SvPV(sv, len);

      if (!len)
         return newSVpvn("", 0);

      {
         const U32 utf8 = SvUTF8(sv);
         const char* p = s+len-1;         
         if (utf8) {
            while (p != s && (*p & 0xC0) != 0xC0)
               --p;
         }

         return newSVpvn_utf8(p, s+len-p, utf8);
      }
   }

__END_OF_C__

use Inline C=>Perl有两种字符串存储格式

其中一种格式使用相同数量的字节(1)来存储字符串可能包含的每个字符。正因为如此,而且Perl跟踪一个字符串使用了多少字节,因此
substr($x,-1)
在这种格式的字符串上的性能并不取决于字符串的长度

上述格式的问题是,它只能存储非常有限的字符范围。它可用于存储Unicode码点“Eric”和“êric”,但不能用于存储“ΕλΔα”。必要时(甚至不必要时),Perl将自动将字符串的存储格式切换为其他格式

第二种格式可以将任何Unicode代码点存储为字符。实际上,它可以存储任何32位或64位的值(取决于
perl
的构建设置)。缺点是使用可变字节数来存储每个字符。因此,即使Perl知道