在 zsh 中,在单个 glob 模式中删除并添加后缀

Owe*_*wen 3 zsh wildcards

假设我有一个名为foo.md.md(双后缀的原因将变得显而易见)的文件。

$ print *.md(om[1]) # Get the most recent .md file
foo.md.md

$ print *.md(om[1]:r) # Strip the suffix
foo.md

$ print *.md(om[1]:r).docx # Try to add a suffix -- oops that doesn't work
zsh: no matches found: *.md(om[1]:r).docx

$ print *.md(om[1]:s/.md/.docx/) # Try another way -- also falls short
foo.docx.md

$ f=(*.md(om[1])); print ${f:r}.docx # Store it in a variable -- works but verbose
foo.md.docx
Run Code Online (Sandbox Code Playgroud)

*.md(om[1]:r)如果我能以某种方式让 zsh在添加新后缀之前将其视为一个完整的模式,那么似乎一切都会好起来。或者,是否有某种方法可以将:s///修饰符锚定到字符串的末尾。

有什么办法可以实现这一点吗?

Sté*_*las 7

另一种方法是使用匿名函数使用参数扩展运算符$@(又名$argv)进行进一步修改:

(){print -r -- ${^@:r}.docx} *.md(om[1])
Run Code Online (Sandbox Code Playgroud)

这样可以节省使用临时数组变量的麻烦。这里仅当包含多个元素^时才需要。$@对于像这样的一个元素,可以简化为:

(){print -r -- $@:r.docx} *.md(om[1])
Run Code Online (Sandbox Code Playgroud)

或者,正如 @Gairfowl 在评论中所建议的:

(){print -r -- $1:r.docx} *.md(om)
Run Code Online (Sandbox Code Playgroud)

不要忘记--(也适用于-),否则您将引入命令注入漏洞!省略-r可能也没有意义。


ste*_*ver 6

:s/l/r如果启用该选项,您似乎可以锚定修饰符HIST_SUBST_PATTERN

~ % print -r -- *.md(om[1]:s/.md/.docx)
foo.docx.md
 ~ % print -r -- *.md(om[1]:s/%.md/.docx)
foo.md.md
 ~ % setopt histsubstpattern
 ~ % print -r -- *.md(om[1]:s/%.md/.docx)
foo.md.docx
Run Code Online (Sandbox Code Playgroud)

不要忘记--(也适用于-),否则您将引入命令注入漏洞!省略-r可能也没有意义。


don*_*sti 6

您可以使用e字符串 glob 限定符REPLY并更改例如的值

print -r -- *.md(om[1]e_'REPLY=${REPLY:r}.docx'_)
Run Code Online (Sandbox Code Playgroud)

不要忘记--(也适用于-),否则您将引入命令注入漏洞!省略-r可能也没有意义。