如何lcfirst每组词?
How to lcfirst each group of words?
为什么这没有像我预期的那样工作?
$ echo 'JOHN, BO PEEP, BoPeep' | perl -0777ne 'map { print ($_) if $_ ne uc($_) } split /,/'
BoPeep
$ echo 'JOHN, BO PEEP, BoPeep' | perl -0777ne 'map { print lcfirst($_) if $_ ne uc($_) } split /,/'
BoPeep
这两个命令之间的唯一区别是 print ($_)
与 print lcfirst($_)
,而我原以为 print lcfirst($_)
会输出 boPeep
。
我错过了什么?
示例输入:
JOHN, BO PEEP, BoPeep, AVG, Hex_String_Literal, Time_String, MODULE
问题是单独使用逗号拆分会在每个术语中留下前导空格。
解决这个问题的一种方法是拆分感兴趣的标记之间的所有内容,这里 /\s*,\s*/
(回想一下 split 那里采用了完整的合法正则表达式)。进行其他简化
echo "JOHN, BO PEEP, BoPeep, AVG, Hex_String_Literal, Time_String, MODULE"
| perl -nlE'$_ ne uc($_) and say lcfirst($_) for split /\s*,\s*/'
这会在单独的一行上打印单词 boPeep
、hex_String_Literal
、time_String
。要将它们清晰地打印在由空格分隔的一行中,我们需要更多一些。例如
perl -nE'say join " ", map { $_ ne uc($_) ? lcfirst($_) : () } split /\s*,\s*/'
这使用了一个技巧来通过 map
进行过滤:return 一个空列表 ()
用于我们要过滤掉的内容(all-caps 个单词),它被展平在整个输出列表中什么都没有。或者,过滤然后进一步处理
perl -nE'say join " ", map { lcfirst($_) } grep { $_ ne uc($_) } split /\s*,\s*/'
这首先处理从 split
到 grep
的列表,然后用 map
遍历剩余项目的输出列表。这可能比一次遍历整个列表的三元组效率低一些,但这肯定不会在任何合理的工作负载中显示出来。
一些评论
我已经删除了 -0777
,因为我不确定它的实用性——如果它在文件上运行并且需要处理文本中的多行块,那么我们需要一些其他规定无论如何。如果它变成 line-by-line 那么就没有必要了。如果需要,把它放回去 :)
那种提供 say
(以及 所有 其他功能!)的便捷 -E
switch 在以下人眼中并不好未来的兼容性。如果这是或可能成为一个问题,那么使用 CORE::say
,或者当然是 print "...", "\n"
,并保留 -e
而不是 -E
为什么这没有像我预期的那样工作?
$ echo 'JOHN, BO PEEP, BoPeep' | perl -0777ne 'map { print ($_) if $_ ne uc($_) } split /,/'
BoPeep
$ echo 'JOHN, BO PEEP, BoPeep' | perl -0777ne 'map { print lcfirst($_) if $_ ne uc($_) } split /,/'
BoPeep
这两个命令之间的唯一区别是 print ($_)
与 print lcfirst($_)
,而我原以为 print lcfirst($_)
会输出 boPeep
。
我错过了什么?
示例输入:
JOHN, BO PEEP, BoPeep, AVG, Hex_String_Literal, Time_String, MODULE
问题是单独使用逗号拆分会在每个术语中留下前导空格。
解决这个问题的一种方法是拆分感兴趣的标记之间的所有内容,这里 /\s*,\s*/
(回想一下 split 那里采用了完整的合法正则表达式)。进行其他简化
echo "JOHN, BO PEEP, BoPeep, AVG, Hex_String_Literal, Time_String, MODULE"
| perl -nlE'$_ ne uc($_) and say lcfirst($_) for split /\s*,\s*/'
这会在单独的一行上打印单词 boPeep
、hex_String_Literal
、time_String
。要将它们清晰地打印在由空格分隔的一行中,我们需要更多一些。例如
perl -nE'say join " ", map { $_ ne uc($_) ? lcfirst($_) : () } split /\s*,\s*/'
这使用了一个技巧来通过 map
进行过滤:return 一个空列表 ()
用于我们要过滤掉的内容(all-caps 个单词),它被展平在整个输出列表中什么都没有。或者,过滤然后进一步处理
perl -nE'say join " ", map { lcfirst($_) } grep { $_ ne uc($_) } split /\s*,\s*/'
这首先处理从 split
到 grep
的列表,然后用 map
遍历剩余项目的输出列表。这可能比一次遍历整个列表的三元组效率低一些,但这肯定不会在任何合理的工作负载中显示出来。
一些评论
我已经删除了
-0777
,因为我不确定它的实用性——如果它在文件上运行并且需要处理文本中的多行块,那么我们需要一些其他规定无论如何。如果它变成 line-by-line 那么就没有必要了。如果需要,把它放回去 :)那种提供
say
(以及 所有 其他功能!)的便捷-E
switch 在以下人眼中并不好未来的兼容性。如果这是或可能成为一个问题,那么使用CORE::say
,或者当然是print "...", "\n"
,并保留-e
而不是-E