尝试使用 解决代码高尔夫问题zsh
,但我的正则表达式无法正常工作。
要求
给定输入字符串$1
,立即删除任何!
字符左侧的所有空格。
例子:
Input ($1) Expected Result:
" ! a! !b c!d !" => "! a!!b c!d!"
"a !" => "a!"
"! a" => "! a"
"! ! !" => "!!!"
"! " => "! "
我想要一个zsh
只使用内置的解决方案,这是我能得到的最接近的:
<<<${(S)1// *!/!}
不幸的是——在线尝试——这会导致
!!!b!d!
! a
!!!
!
正如你所看到的,第一行被*
比赛过于热情地破坏了。zsh 文档(指南的第 5.9.2 和 5.9.3节)在这一点上相当混乱。
优先运算符+
也不起作用:(<<<${(S)1//+( )!/!}
这不是通常的正则表达式语法中的正则表达式。这是一个通配符模式。sh 通配符模式不如正则表达式表达。Ksh、bash 和 zsh 具有与正则表达式一样富有表现力的通配符模式,但语法不同。另请参阅为什么我的正则表达式在 X 中有效,但在 Y 中无效?
在 zsh 中执行此操作的正常方法是打开该
extended_glob
选项(几乎每个人几乎一直都这样做)并使用与前面任意数量匹配的#
通配符*
(就像在通常的正则表达式语法中一样)。您的尝试失败有两个原因。首先,
*
通配符模式表示“任何字符序列”。其次,非贪心匹配会破坏目的:它会导致没有空间匹配。在 ksh、bash after
shopt -s extglob
和 zsh aftersetopt ksh_glob
中,您可以使用*( )
匹配零个或多个空格,或+( )
匹配一个或多个空格。要么在这里做。对于正常使用,您只需打开
extended_glob
. 对于代码高尔夫来说,这是一个相当高的代价。也许你可以缩小空间爆炸以循环爆炸:repeat $#a a=${a/ !/!}
. 或者您可以输入“zsh withextended_glob
turn on”类别,这是编写 zsh 补全函数的语言。