Zsh:是否可以使用变量的值作为替换模式?

Zsh:是否可以使用变量的值作为替换模式?

是否可以执行以下操作?

g=$f:s/$in/$out/;

或者

g=$g:s/$in[$i]/$out[$i]/;

我尝试过随机字符组合,例如${~in}和 ,g=$g:ps/但是,正如你所看到的,我不是 zsh 专家——猜测对我没有任何帮助:-)我什至尝试阅读手册页...

编辑:我正在尝试编写自己的 zmv 类型命令:

# in   a*b* -> a b NULL     rn a*b* *c*d   aXXbYY  -->  XXcYYd
# out  *c*d -> NULL c d     rn inv* mag*   inv.ext inv.spc -->  mag.ext mag.spc

alias rn='noglob frn'

function frn() {                                                                                                   
    local in out m n f g i
    setopt localoptions glob histsubstpattern

    in=("${(@s:*:)1}")                          # split $1 and $2 on '*'
    out=("${(@s:*:)2}")                         # keeping NULL fields

    m=${#in[@]}                                 # count n(array-elements)
    n=${#out[@]}

    if [[ $m = $n ]] {
        foreach f ($~1)                         # foreach file in globbed $1
            g=$f
            for (( i = 1; i < n; i += 1 )); do
                g=$g:s/$in[$i]/$out[$i]/        # subst corresponding fields
            done

            g=$g:s/%$in[$i]/$out[$i]/           # last subst has % anchor

            print '$f --> $g'
            mv $f $g
        end
    } else {
        print "n(*) must be same for both patterns"
    }
}

答案1

$out与展开的不同,$in这里被视为文字字符串......所以什么也没有发生(除非字面f包含$in)。
要在左侧展开,您需要HIST_SUBST_PATTERN:

s/l/r[/]

r如下所述替代l
......
默认情况下,替换的左侧不是模式,而是字符串[...]
......如果 设置了
该选项,则为被视为文件名生成中描述的通常形式的模式。HIST_SUBST_PATTERNl

所以

setopt histsubstpattern

然后它应该可以工作......

答案2

您尝试和重新实现的方法zmv -W非常脆弱。

rfn a*b*c b*c*d应用到acrobatic它应该更改为bcrocatid,你会尝试做

  • a -> b
  • b -> c
  • c -> d

连续,但这会产生:

  • 杂技 -> 杂技
  • 杂技 -> 杂技
  • 杂技 -> 杂技

zmv -W只需按照同样的方式进行即可

  1. 更改a*b*c模式以(#b)a(*)b(*)c启用反向引用
  2. b*c*d替换更改为b$match[1]c$match[2]d
  3. 并使用Korn 风格${var/pattern/replacement}或 csh-stype执行一次替换,或者使用 zsh 6.0+执行一次替换$var:s/pattern/replacementhistsubstpattern:S修饰语它使用带或不带 的模式histsubstpattern
function frn {
  emulate -L zsh
  set -o extendedglob
  local glob=$1 replacement=$2 n=0 file newfile

  pattern=${glob//'*'/'(*)'}
  replacement=${replacement//(#m)'*'/\$match[$((++n))]}

  for file ($~glob) {
    newfile=${file/#%(#b)$~pattern/${(Xe)replacement}}
    if [[ -n $newfile && $file != $newfile ]] {
      print -ru2 -- "${(q+)file} -> ${(q+)newfile}"
      # mv -- $file $newfile
    }
  }
}
alias frn='noglob frn'

然后:

$ frn a*b*c b*c*d
acrobatic -> bcrocatid

与...一样:

$ alias zmvw='noglob zmv -W'
$ zmvw -n a*b*c b*c*d
mv -- acrobatic bcrocatid

except 不仅zmv可以处理更多的通配符,*还可以进行更多的健全性检查和错误处理。

相关内容