Regex 在Perl中从字符串中删除换行符
我有一个从文本文件中读取的字符串,但在Ubuntu Linux中,我尝试从末尾删除它的换行符 我用了所有的方法。但是对于Regex 在Perl中从字符串中删除换行符,regex,string,perl,Regex,String,Perl,我有一个从文本文件中读取的字符串,但在Ubuntu Linux中,我尝试从末尾删除它的换行符 我用了所有的方法。但是对于s/\n |\r/-/(我查看它是否找到了替换任何新行字符串的字符串),它替换了字符串,但在我打印它时仍会转到下一行。此外,当我使用chomp或chop时,字符串被完全删除。我找不到其他解决办法。我如何解决这个问题 use strict; use warnings; use v5.12; use utf8; use encoding "utf-8"; open(MYINPUT
s/\n |\r/-/
(我查看它是否找到了替换任何新行字符串的字符串),它替换了字符串,但在我打印它时仍会转到下一行。此外,当我使用chomp
或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);
使用严格;
使用警告;
使用v5.12;
使用utf8;
使用编码“utf-8”;
打开(MYINPUTFILE,“您可以使用以下方法擦除换行符:
$line =~ s/[\n\r]//g;
但是,当您这样做时,您需要更改if
语句中的正则表达式以避免查找它们。我也不认为您希望在if
中有/g
。您也不应该有$line2
我也不会做这种事:
print $line2." WRONG FORMAT!\n";
你能行
print "$line2 WRONG FORMAT!\n";
…相反。此外,print接受一个列表,因此您可以使用逗号,而不是串联字符串。您可以执行以下操作:
=~tr/\n/
但实际上,chomp
应该能起作用:
while (<filehandle>){
chomp;
...
}
while(){
咀嚼;
...
}
另外,s/\n |\r/
仅替换第一次出现的\r
或\n
。如果要替换所有出现的值,则需要在s/\r |\n//g
末尾使用全局修饰符
注意:如果您在windows中包含\r
,它通常以\r\n
结尾,因此您需要同时替换这两个部分(例如s/(?:\r\n |\n)/
),当然是上面的语句(s/\r\n//g
)使用全局修饰符无论如何都会解决这个问题。您可能遇到Windows文件结尾的一行导致问题。例如,“foo-bar\n”之类的字符串实际上是“foo-bar\r\n”。在Ubuntu上使用chomp
时,您将删除其中包含的任何内容,即“\n”。所以,剩下的是“foo-bar\r”
这是一个微妙但非常常见的错误。例如,如果打印“foo bar\r”并添加换行符,则不会注意到错误:
my $var = "foo bar\r\n";
chomp $var;
print "$var\n"; # Remove and put back newline
但是,当您将该字符串与另一个字符串连接时,会覆盖第一个字符串,因为\r
会将输出句柄移动到字符串的开头。例如:
print "$var: WRONG\n";
它实际上是“foo bar\r:error\n”,但是\r
之后的文本将导致以下文本在第一部分的顶部换回:
foo bar\r # \r resets position
: WRONG\n # Second line prints and overwrites
当第一行比第二行长时,这一点更加明显。例如,请尝试以下操作:
perl -we 'print "foo bar\rbaz\n"'
您将获得以下输出:
baz bar
解决方案是删除错误的行尾。您可以使用dos2unix
命令,或者直接在Perl中使用以下命令:
$line =~ s/[\r\n]+$//;
另外,请注意,您的其他代码有点可怕。例如,您认为$13
包含什么?这是您以前的正则表达式中第13个括号捕获的字符串。我非常确定该值将始终是未定义的,因为您没有13个括号
您声明了两组$id
和$name
。一个在循环外,一个在顶部。这是一种非常糟糕的做法,依我看。只声明所需范围内的变量,而决不要将所有声明都堆在脚本顶部,除非您明确希望它们是文件的全局声明
当它们具有相同的值时,为什么要使用$line
和$line2
?只需使用$line
说真的,这是怎么回事:
if ($line !~ /^(((\X|[^\W_ ])+)(.docx)(\n|\r))/g) {
这看起来像是试图混淆,没有冒犯。三个嵌套的否定和一堆不必要的括号
首先,因为它是if-else,所以只需交换它并反转正则表达式即可。其次,[^\W\uz]
双重否定相当令人困惑。为什么不直接使用[a-Za-z0-9]
?您可以将其拆分,以便于解析:
if ($line =~ /^(.+)(\.docx)\s*$/) {
my $pre = $1;
my $ext = $2;
删除Unicode换行符(包括CRLF对)的正确方法是使用v5.10中引入的\R
regex元字符
强烈反对使用use encoding
pragma。您应该使用使用open
pragma,或者在3-argopen
上的mode参数中使用编码,或者使用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//;
...
}
使用v5.10;#最低Perl版本以获得\R支持
使用utf8;#源在UTF-8中
使用警告qw(致命utf8);#编码错误引发异常
使用openqw(:utf8:std);#默认的打开模式,`backticks`和std{in,out,err}在UTF-8中
而(){
s/\R\z/;
...
}
[^\W_u33;]
?因此,您正在尝试匹配非[A-Za-z0-9_33;
,而不是下划线。
?这是很多否定,你确定你说的对吗?我自己觉得很困惑。@TLP请不要假装Perl字符类有ASCII定义,因为这在Perl中是非常错误的。你必须使用。@tchrist你在说什么?那\w
不是equa是的,当然不是。\w
等于[\p{字母}\p{Mark}\p{Decimal\u Number}\p{Connector\u标点符号}]
。这是众所周知的。从Unicode v6.0开始,它覆盖了102724个代码点,比您提到的不足63个代码点多了四个数量级。@stackoverflow,前提是$data=~s/\R//g
可以工作;请注意,我删除了\z
边界。不确定为什么要删除所有新行。$/=undef;$data=;data=~s/\R//g;
。?@stackoverflow当然可以。
$variable = join('',split(/\n/,$variable))