为什么此 Perl Regex 单行代码没有使用修饰符使完整结果大写\U
?
我预计MY_NICE_WORD
。
$ perl -pe 's/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/\U$1_$2\E/g' <(echo 'myNiceWord HTTPHeader')
my_Nice_Word HTTP_Header
根据文档,
The following escape sequences are available in constructs that interpolate, but not in transliterations.
\l lowercase next character only
\u titlecase (not uppercase!) next character only
\L lowercase all characters till \E or end of string
\U uppercase all characters till \E or end of string
\F foldcase all characters till \E or end of string
\Q quote (disable) pattern metacharacters till \E or
end of string
\E end either case modification or quoted section
(whichever was last seen)
来源:man --pager 'less -p "The following escape sequences are available in constructs that interpolate, but not in transliterations."' perlop
替换文本不是在插值上下文中吗?
工作示例
根据我的理解,遵循文档后我可以提供这个工作示例:
$ perl -pe 's/(hello)/\U$1\E/g' <(echo hello)
HELLO
正则表达式来自https://stackoverflow.com/a/1176023/1236128
-> 这涵盖的重要情况:HTTPHeader 不会变成 h_t_t_p_header,而是HTTP_Header
(或大写的 HTTP_HEADER)
您正在使用前瞻(
(?=…)
)和后瞻((<?=…)
)断言,没有任何内容可以匹配和替换。我认为这就是您想要实现的目标,即在每个大写字母前面添加下划线,然后将整个字符串大写:
但,
所以也许
如果这就是您要去的地方,那么更容易将“单词”按大写字母拆分,用 连接各个部分
_
,然后将结果大写:我发现两个问题:您使用了零宽度断言。我认为无法一次性完成此操作。
这对你有用吗:
它在 myFWord 上失败了。
这个答案解决了 OP 问题,即当使用 0 宽度匹配时,使结果大写/无法在组捕获上使用 \U(并继续使用相同的正则表达式):
答案是你不能在使用 $1 和 $2
的零宽度(?<=...) 或 (?=...) 的组匹配器上使用 \U \E,因为它们不是捕获组,而是查看运算符 (感谢 Stéphane Chazelas)解决此限制的一种方法是在不改变原始表达式的情况下对结果进行后处理,如下所示:
使用 Perl 特殊变量
$_
来对应用于字符串的表达式的输出进行处理:$_ = uc($_)
其中uc
是 Perl 中的内置大写函数,将结果转换为大写。附言:muru 的评论回答了为什么 \U 不起作用的问题,这也是我写这篇回答的动机。谢谢。