Perl脚本在检查输入中的文本时在'符号处停止

rdlzhqv9  于 2022-11-15  发布在  Perl
关注(0)|答案(1)|浏览(227)

我不知道Perl,我有一个脚本,应该从输入中删除特殊字符。
脚本如下所示:

use utf8;
use strict;
use warnings;

use open qw/ :std :encoding(utf-8) /;
use Encode qw(encode decode);
my $str = $ARGV[0];
$str = decode('utf8',shift);
$str =~ s/[^a-zA-Z0-9 \n@.\\,\",\/,\\,<,>,{,},(,),;,:,=,?,¦,%,#,\&,+,*,',!,\$,^,\-,_,–,ä,ü,ö,ß,é,à,è,ù,â,ê,î,ô,û,ç,ë,ï]/ /gi;
print $str;

作为输入的示例文本:

  • '2022年4月7日15:16:10 UPCIT\用户1:INFO:相关工单INC 00112233已将其状态从“进行中”更改为“待定”'*

您将注意到输入文本行在控制台中用“”(单引号)引起来,如下所示

perl /pathtothescript/scriptname.pl 'text to process with the script'

输出示例:
只有程序退出并返回错误代码130时才不会有输出,因为我已经在堆栈时终止了脚本。
有没有人对什么可能导致脚本在到达文本中的'符号时停止提出建议?
这是我在我的本地机器上执行的几个测试的样本。同时要指出的是,测试是在Ubuntu上完成的,脚本将在Redhat上运行,我不是100%确定这与此有什么关系...

bmp9r5qi

bmp9r5qi1#

首先,有几个基本的问题需要澄清,问题的真实意图是什么(而且几乎是正确的),并提出可能更有条理的方法来做这件事。
注解中提供了要保留的字符列表。

use strict;
use warnings;
use feature 'say';

use utf8;                              # for what's in this source
use Encode qw(decode);                 # for what need be manually decoded
use open qw( :std :encoding(UTF-8) );  # takes care of standard streams

my $str = decode('UTF-8', shift, Encode::FB_CROAK);

# Characters to keep
my $ch_non_ascii = q(ä ü ö ß é à è ù â ê î ô û ç ë ï);
my $punct_symb = 
    q(@ , . " \/ \ < > { } ( ) # ; : = ? ¦ | % & + * ' ! $ ^ - –);

# Note: typed with spaces for readability but then spaces will be kept.  
# Can keep it like that but now remove spaces from these variables and
# then they will be removed from input as well, if that is desired
#s/\s+//g for $ch_non_ascii, $punct_symb;

my $re_del = qr/[^\w $punct_symb $ch_non_ascii]+/xx;  # \w --> [a-zA-Z0-9_]

# Or consider using POSIX classes, at least [:punct:]. See text

$str =~ s/$re_del//g;

say $str;

qr运算符生成一个正确的正则表达式模式。q()是一个单引号形式的运算符。使用/xx修饰符,字符类中的所有空格都被忽略,这对可读性很有用(Perl v5.26提供)。
正在运行(注意双引号)

script.pl "a,B.!'{)] /\@^~ ö ß ≠"

印刷品

a,B.!'{) /@^ ö ß

~]\已被删除,因为它们没有被列出以保留。如果您使用[:punct:],而不是手动列出标点/符号,则只有会被删除,因为POSIX类包含了其他标点/符号(由于疏忽而从列表中省略了?)。包含的字符列表在perlrecharclass的脚注5中。
另一种可能更干净、更安全的方法是使用POSIX字符类,特别是Perl为它们添加的标点符号和/或Unicode属性。参见perlrecharclass和perluniprops中的POSIX字符类(与perlunicodeperluniintro一起)。
如果这对您的需求来说足够好,那么这就变得微不足道了

$str =~ s/[^ [:alnum:] $ch_non_ascii [:punct:] ]+//gxx;
# or
$str =~ s/[^ \p{PosixAlnum} $ch_non_ascii \p{XPosixPunct} ]+//gxx;
# or, including full-range unicode
$str =~ s/[^ \p{XPosixAlnum} \p{XPosixPunct} ]+//gxx;

POSIX类和它们对应的Unicode属性可能会在这里或那里有所不同,请参阅文档和实验。我将字符类中的元素隔开只是为了可读性。
这些都是普通的字符类,其中包含[:punct:]\p{...},因此,如果有更多的字符要删除,而这些字符不在预定义的POSIX/Unicode集中,请添加到这些字符类中。
有关详细信息,请参阅链接的文档。
对问题中一些细节的评论

  • 这个问题问的是输入中的'字符。这是关于如何输入输入--也是关于你的shell、文件、管道等等。如何读取输入取决于它是如何提供的。如果它是直接从命令行输入的,通常应该用双引号引起来。

如果你需要向程序传递一些非常特殊的东西,而这些东西可能会使shell感到困惑,那么一种方法就是把它们放在一个文件中,然后读取这个文件。

  • 字符类只列出字符(字符之间没有逗号!),因此在正则表达式中,这些字符中的任何一个都可以被它匹配。如果它以^开头,比如[^...],那么任何没有在其中列出的字符都可以被匹配--这是一个“非”字符类。从perlretut开始。
  • @ARGV中读取一个$str--然后再从它中读取一个shift-艾德。不需要两者都有。
  • 注意,写入utf8UTF-8可能不同;请参阅Encode中的此内容

相关问题