perl中匹配特殊字符(#@#!~`%^&()[]}{;')并替换为_(下划线)
Matching special character (#@#!~`%^&()[]}{;') and replace it with _ (underscore) in perl
我想删除除这 2 个字符之外的所有特殊字符。-
$name=~s/[^\w\d\.-]/_/g ;
但它上面的行不仅删除了特殊字符,还删除了非字母字符,例如阿拉伯语或其他 none 字母字符。
如何只删除这些字符 (#@#!~`%^&()[]}{;',)
根据 Gene 的评论,指定要替换的内容,但我会转义每个特殊字符。注意,要替换#,请在字符数组中使用 \#\#,如第 2 行所示:
$name = "@ # R ! ~## ` % ^ & ( O ){{();,'`@@ { } ;!!! ' N , ";
$name =~ s/[\@\!\~\`\%\&\^\(\)\{\}\;\'\,\#\#]//g;
$name =~ s/ *//g;
print $name;
### Outputs RON
这里有几件事需要考虑。
首先,\d
和 \w
真的按照您的想法行事吗?最近的 perls 是 Unicode 感知的(在某些情况下是区域设置感知的),那些 character classes aren't the same in every situation.
既然你知道你要排除什么,你可以直接把它放在字符class中。您只需要转义 ]
所以它不会结束字符 class:
use v5.10;
my $name = "(Hello] #&^% {World[} (#@#!~`%^&()[]}{;',)!";
$name =~ s/[(#@#!~`%^&()[\]}{;',)]/_/g;
say $name;
Mark Jason Dominus 撰写了有关清理数据的“美国”和“普鲁士”方法的文章。您可以指定要排除或包含的内容。
如果您指定要排除的内容,您可能会忽略一些您应该排除但没有排除的内容。这可能是因为您忘记了或者甚至不知道您应该排除它。这些意想不到的情况可能会咬你。
如果你只指定安全的东西,你可能会错过你应该通过的东西,但坏的东西不会因为遗漏的错误而通过。
然后你可以试试这个,你不使用字符 class 快捷方式:
$name =~ s/[^0-9A-Za-z.-]/_/g;
但是输出有点奇怪,因为这也替换了空格。您可以在其中添加 \s
快捷方式:
$name =~ s/[^0-9A-Za-z\s.-]/_/g;
但是 meaning of \s
has also changed over time too(垂直制表符!)也是 Unicode 识别的。您可以列出您会接受的空格:
$name =~ s/[^0-9A-Za-z\x20.-]/_/g;
但是不,这有点奇怪。还有另一种方法。你可以回到 ASCII versions of the character class shortcuts with the /a
flag:
$name =~ s/[^\d\w\s.-]/_/ga;
正则表达式运算符标志位于 perlop since they apply to an operator. But, for as long as I've been using Perl and telling that to people in classes, someone I still go to perlre 前面。
音译
其次,替换运算符可能比您需要的更多。如果您想将单个字符更改为其他单个字符,音译运算符可能就是您所需要的。它用右边对应的字符改变左边的字符:
$name =~ tr/abc/XYZ/; # a -> X, b -> Y, c -> Z
如果右边没有足够的字符匹配,它会重复使用最后一个字符:
$name =~ tr/abc/XY/; # a -> X, b -> Y, c -> Y
所以,在你的情况下有一个下划线:
$name =~ tr/@#!~`%^&()[]}{;',/_/;
由于 tr///
中的字符序列不是正则表达式,因此您不必担心元字符。
只是为了咯咯笑
如果您希望在多个地方使用此模式,您可能需要为它取一个带有 user-defined Unicode property 的名称。一旦它有了名字,你就可以在任何地方使用它并且可以同时为每个人更新:
use v5.10;
my $name = "(Hello] #&^% {World[} (#@#!~`%^&()[]}{;',)!";
$name =~ s/\p{IsForbidden}/_/g;
say $name;
sub IsForbidden {
# see https://perldoc.perl.org/perlunicode#User-Defined-Character-Properties
state $exclude = q|@#!~`%^&()[]}{;',|;
state $string =
join '',
map { sprintf "%X\n", ord }
split( //, $exclude );
return $string;
}
我想删除除这 2 个字符之外的所有特殊字符。-
$name=~s/[^\w\d\.-]/_/g ;
但它上面的行不仅删除了特殊字符,还删除了非字母字符,例如阿拉伯语或其他 none 字母字符。
如何只删除这些字符 (#@#!~`%^&()[]}{;',)
根据 Gene 的评论,指定要替换的内容,但我会转义每个特殊字符。注意,要替换#,请在字符数组中使用 \#\#,如第 2 行所示:
$name = "@ # R ! ~## ` % ^ & ( O ){{();,'`@@ { } ;!!! ' N , ";
$name =~ s/[\@\!\~\`\%\&\^\(\)\{\}\;\'\,\#\#]//g;
$name =~ s/ *//g;
print $name;
### Outputs RON
这里有几件事需要考虑。
首先,\d
和 \w
真的按照您的想法行事吗?最近的 perls 是 Unicode 感知的(在某些情况下是区域设置感知的),那些 character classes aren't the same in every situation.
既然你知道你要排除什么,你可以直接把它放在字符class中。您只需要转义 ]
所以它不会结束字符 class:
use v5.10;
my $name = "(Hello] #&^% {World[} (#@#!~`%^&()[]}{;',)!";
$name =~ s/[(#@#!~`%^&()[\]}{;',)]/_/g;
say $name;
Mark Jason Dominus 撰写了有关清理数据的“美国”和“普鲁士”方法的文章。您可以指定要排除或包含的内容。
如果您指定要排除的内容,您可能会忽略一些您应该排除但没有排除的内容。这可能是因为您忘记了或者甚至不知道您应该排除它。这些意想不到的情况可能会咬你。
如果你只指定安全的东西,你可能会错过你应该通过的东西,但坏的东西不会因为遗漏的错误而通过。
然后你可以试试这个,你不使用字符 class 快捷方式:
$name =~ s/[^0-9A-Za-z.-]/_/g;
但是输出有点奇怪,因为这也替换了空格。您可以在其中添加 \s
快捷方式:
$name =~ s/[^0-9A-Za-z\s.-]/_/g;
但是 meaning of \s
has also changed over time too(垂直制表符!)也是 Unicode 识别的。您可以列出您会接受的空格:
$name =~ s/[^0-9A-Za-z\x20.-]/_/g;
但是不,这有点奇怪。还有另一种方法。你可以回到 ASCII versions of the character class shortcuts with the /a
flag:
$name =~ s/[^\d\w\s.-]/_/ga;
正则表达式运算符标志位于 perlop since they apply to an operator. But, for as long as I've been using Perl and telling that to people in classes, someone I still go to perlre 前面。
音译
其次,替换运算符可能比您需要的更多。如果您想将单个字符更改为其他单个字符,音译运算符可能就是您所需要的。它用右边对应的字符改变左边的字符:
$name =~ tr/abc/XYZ/; # a -> X, b -> Y, c -> Z
如果右边没有足够的字符匹配,它会重复使用最后一个字符:
$name =~ tr/abc/XY/; # a -> X, b -> Y, c -> Y
所以,在你的情况下有一个下划线:
$name =~ tr/@#!~`%^&()[]}{;',/_/;
由于 tr///
中的字符序列不是正则表达式,因此您不必担心元字符。
只是为了咯咯笑
如果您希望在多个地方使用此模式,您可能需要为它取一个带有 user-defined Unicode property 的名称。一旦它有了名字,你就可以在任何地方使用它并且可以同时为每个人更新:
use v5.10;
my $name = "(Hello] #&^% {World[} (#@#!~`%^&()[]}{;',)!";
$name =~ s/\p{IsForbidden}/_/g;
say $name;
sub IsForbidden {
# see https://perldoc.perl.org/perlunicode#User-Defined-Character-Properties
state $exclude = q|@#!~`%^&()[]}{;',|;
state $string =
join '',
map { sprintf "%X\n", ord }
split( //, $exclude );
return $string;
}