我遇到了一个包含此参数扩展的 zsh 脚本
${LBUFFER%%(#m)[_a-zA-Z0-9]#}
对于任何想知道这个表达所处的上下文的人来说,它是zle 小部件功能,提供类似 vim 的缩写
其基本形式显然是后缀修剪。 IE${name%%pattern}
即来自man zshexpn
- 参数扩展
${name%pattern} ${name%%pattern} If the pattern matches the end of the value of name, then sub‐ stitute the value of name with the matched portion deleted; [...]
关于参数扩展标志 (#m)
: 从man zshexpn
# Evaluate the resulting words as numeric expressions and output the characters corresponding to the resulting integer. Note that this form is entirely distinct from use of the # without parentheses. m Only useful together with one of the flags l or r or with the # length operator when the MULTIBYTE option is in effect. Use the character width reported by the system in calculating how much of the string it occupies or the overall length of the string. Most printable characters have a width of one unit, however cer‐ tain Asian character sets and certain special effects use wider characters; combining characters have zero width. Non-printable characters are arbitrarily counted as zero width; how they would actually be displayed will vary.
关于这[_a-zA-Z0-9]#
部分,这显然是从字符串末尾删除的模式LBUFFER
,但这是正则表达式模式还是某种正则表达式通配混合?
它是 zsh 特定的“extended_glob”模式的一部分吗?,即来自man zshoptions
EXTENDED_GLOB Treat the `#', `~' and `^' characters as part of patterns for filename generation, etc. (An initial unquoted `~' always pro‐ duces named directory expansion.)
这个 zsh 参数扩展有什么作用?
答案1
看起来这是一个 zsh“扩展 glob”表达式。
即来自man zshexpn
通配标志
有多种标志会影响其右侧的任何文本,直到封闭组的末尾或模式的末尾;它们需要 EXTENDED_GLOB 选项。全部采用 (#X) 形式,其中 X 可以采用以下形式之一:[...]
m
设置对整个匹配字符串的匹配数据的引用;这类似于反向引用,并且在文件名生成中不起作用。该标志必须在模式末尾有效,即不是组的本地标志。参数 $MATCH、$MBEGIN 和 $MEND 将分别设置为匹配的字符串以及字符串开头和结尾的索引。这在参数替换中最有用,否则匹配的字符串是显而易见的。例如,
arr=(veldt jynx grimps waqf zho buck) print ${arr//(#m)[aeiou]/${(U)MATCH}}
强制所有匹配项(即所有元音)变为大写,打印“vEldt jynx grImps wAqf zhO bUck”。与反向引用不同,除了在所示示例等情况下替换字符串所需的额外替换之外,使用匹配引用不会造成速度损失。
该#
运算符是所谓的“闭包”或重复匹配运算符,相当于*
正则表达式
正如这里所解释的http://zsh.sourceforge.net/Guide/zshguide05.html#l139
所以基本上,这个参数扩展:
${LBUFFER%%(#m)[_a-zA-Z0-9]#}
将启动正则表达式样式的反向引用,从任何匹配的模式在变量(如BRE 或PCRE)(#m)
中可用的位置开始。 因为就像,将匹配字符集中的零个或多个字符。$MATCH
\1
$1
#
*
[_a-zA-Z0-9]#
[_a-zA-Z0-9]