从Perl中的字符串中删除换行符

ero*_*gol 6 regex string perl

我有一个从文本文件中读取的字符串,但在Ubuntu Linux中,我尝试从最后删除它的换行符.

我用过所有的方式.但是s/\n|\r/-/(我看它是否发现任何替换任何新的行字符串)它替换了字符串,但是当我打印它时它仍然会进入下一行.而且,当我使用chompor时chop,字符串被完全删除.我找不到任何其他解决方案.我该如何解决这个问题?

use strict;
use warnings;
use v5.12;
use utf8;
use encoding "utf-8";

open(MYINPUTFILE, "<:encoding(UTF-8)", "file.txt");

my @strings;
my @fileNames;
my @erroredFileNames;

my $delimiter;
my $extensions;
my $id;
my $surname;
my $name;

while (<MYINPUTFILE>)
{
    my ($line) = $_;
    my ($line2) = $_;
    if ($line !~ /^(((\X|[^\W_ ])+)(.docx)(\n|\r))/g) {
        #chop($line2);
        $line2 =~ s/^\n+//;
        print $line2 . " WRONG FORMAT!\n";
    }
    else {
        #print "INSERTED:".$13."\n";
        my($id) = $13;
        my($name) = $2;
        print $name . "\t" . $id . "\n";
        unshift(@fileNames, $line2);
        unshift(@strings, $line2 =~ /[^\W_]+/g);
    }
}
close(MYINPUTFILE);
Run Code Online (Sandbox Code Playgroud)

tch*_*ist 17

删除Unicode换行字形(包括CRLF对)的正确方法是使用\Rv5.10中引入的正则表达式字符.

use encoding编译指示被强烈弃用.您应该使用use openpragma,或者在3-arg的mo​​de参数中使用编码open,或者使用binmode.

 use v5.10;                     # minimal Perl version for \R support
 use utf8;                      # source is in UTF-8
 use warnings qw(FATAL utf8);   # encoding errors raise exceptions
 use open qw(:utf8 :std);       # default open mode, `backticks`, and std{in,out,err} are in UTF-8

 while (<>) {
     s/\R\z//;
     ...
 }
Run Code Online (Sandbox Code Playgroud)


TLP*_*TLP 10

您可能遇到一个以Windows文件结尾的行导致问题.例如,诸如"foo bar \n"之类的字符串实际上将是"foo bar\r \n".chomp在Ubuntu上使用时,您将删除变量中$/包含的任何内容,即"\n".那么,剩下的就是"foo bar\r \n".

这是一个微妙但非常常见的错误.例如,如果您打印"foo bar\r \n"并添加换行符,则不会发现错误:

my $var = "foo bar\r\n";
chomp $var;
print "$var\n";  # Remove and put back newline
Run Code Online (Sandbox Code Playgroud)

但是当您将字符串与另一个字符串连接时,您将覆盖第一个字符串,因为\r将输出句柄移动到字符串的开头.例如:

print "$var: WRONG\n";
Run Code Online (Sandbox Code Playgroud)

它实际上是"foo bar\r \n:WRONG \n",但后面的文本\r会导致以下文本回到第一部分的顶部:

foo bar\r           # \r resets position
 : WRONG\n          # Second line prints and overwrites
Run Code Online (Sandbox Code Playgroud)

当第一行比第二行长时,这更明显.例如,尝试以下操作:

perl -we 'print "foo bar\rbaz\n"'
Run Code Online (Sandbox Code Playgroud)

你会得到输出:

baz bar
Run Code Online (Sandbox Code Playgroud)

解决方案是删除坏线结尾.您可以使用该dos2unix命令执行此操作,也可以直接在Perl中执行以下操作:

$line =~ s/[\r\n]+$//;
Run Code Online (Sandbox Code Playgroud)

此外,请注意您的其他代码有点可怕.例如你认为$13包含什么?这是你前一个正则表达式中第13个括号所捕获的字符串.我很确定该值始终未定义,因为您没有13个括号.

你宣布两套$id$name.一个在循环外面,一个在顶部.这是非常糟糕的做法,IMO.只在他们需要的范围内声明变量,并且永远不要将所有声明都放在脚本的顶部,除非您明确要求它们对文件是全局的.

为什么使用$line$line2何时具有相同的价值?只是用$line.

而且严重的是,这是怎么回事:

if ($line !~ /^(((\X|[^\W_ ])+)(.docx)(\n|\r))/g) {
Run Code Online (Sandbox Code Playgroud)

这看起来像是试图混淆,没有冒犯.三个嵌套的否定和一堆不必要的括号?

首先,因为它是一个if-else,只需交换它并反转正则表达式.其次,[^\W_]双重否定是相当混乱的.为什么不用[A-Za-z0-9]?您可以拆分它以便更容易解析:

if ($line =~ /^(.+)(\.docx)\s*$/) {
    my $pre = $1;
    my $ext = $2;
Run Code Online (Sandbox Code Playgroud)


Gol*_*wby 7

您可以使用以下内容擦除换行符:

$line =~ s/[\n\r]//g;
Run Code Online (Sandbox Code Playgroud)

但是,当您这样做时,您需要更改if语句中的正则表达式而不是查找它们.我也并不认为你想/g在你的if.你真的不应该有$line2.

我也不会做这种事情:

print $line2." WRONG FORMAT!\n";
Run Code Online (Sandbox Code Playgroud)

你可以做

print "$line2 WRONG FORMAT!\n";
Run Code Online (Sandbox Code Playgroud)

......而是.此外,print接受一个列表,因此您可以只使用逗号代替串联字符串.