在 zsh 提示符下重复 char n 次

在 zsh 提示符下重复 char n 次

我正在处理自定义 ZSH 提示,我想n在字符串中重复一个字符次(例如用于填充的空格)。该字符串被打印print -rP(该-r标志忽略回显转义约定,并且该-P标志执行提示扩展)。

我有使用某种字符串替换的工作代码,但我不知道它是如何工作的。由于某种原因,我必须将要打印的字符数乘以二,这感觉就像黑客。

$ n=3
$ c='a'
$ print -rP "${(l:$n::$c:)}" # why doesn't this work?
ca
$ print -rP "${(l:(( $n * 2 ))::$c:)}" # but this does?
aaa

那么,1)为什么乘以 2 时会起作用,2)在字符串中重复字符的正确语法是什么?

答案1

1)为什么乘以二会有效,

展开式"${(l:3::$c:)}"展开为c$cwhile"${(l:3*2::$c:)}"展开为$c$c$c.如果设置了该选项PROMPT_SUBST并且该字符串用作提示字符串的一部分,则会对其进行参数扩展、命令替换和算术扩展的评估。因此,如果c=a,则c$c成为ca$c$c$c成为aaa

用集合测试XTRACE

$ n=3 c=a zsh -o PROMPT_SUBST -xc 'print -rP -- "${(l:n::$c:)}"'
+zsh:1> print -rP -- 'c$c'
ca
$ n=3 c=a zsh -o PROMPT_SUBST -xc 'print -rP -- "${(l:n*2::$c:)}"'
+zsh:1> print -rP -- '$c$c$c'
aaa

2)在字符串中重复字符的正确语法是什么?

参数l扩展标志的使用方式与您已经使用它的方式相同。但是,p应该使用该标志来允许在填充之前$c将字符串参数视为变量的值c(感谢@StéphaneChazelas 指出了这一点)。

$ n=3 c=a zsh -xc 'print -r -- "${(pl:n::$c:)}"'
+zsh:1> print -r -- aaa
aaa

请注意,这是此构造接受的唯一参数扩展形式,根据man zshexpn(在有关参数扩展标志的部分中):

pprint识别与此参数后面描述的任何标志的内置字符串参数   相同的转义序列。

或者,使用此选项,字符串参数可以采用以下形式,$var在这种情况下,将替换变量的值。请注意,此形式是严格的;字符串参数不进行一般参数扩展。

答案2

使用你原来的符号,你可以实现你想要的,p使用开始参数标志

 print "${(pl:$n::$c:)}"

有关更多信息和其他一些有用的示例,请参阅 部分5.4.6:更多参数标志第5章:替补zsh 指南。它提到了 uppercase P,但没​​有p


这里有一些其他参数标志;我正在重复其中的一些内容。一个非常有用的方法是t告诉您参数的类型。这也在第 3 章中出现。它最常见的用途是在尝试使用参数之前测试参数的基本类型:

  if [[ ${(t)myparam} != *assoc* ]]; then
    # $myparam is not an associative array.  Do something about it.
  fi

另一种非常有用的类型是对字符串进行左或右填充,达到指定的长度,并且可以选择使用指定的填充字符串来代替空格;您甚至可以指定一个一次性字符串紧邻相关字符串。

  foo='abcdefghij'
  for (( i = 1; i <= 10; i++ )); do
   goo=${foo[1,$i]}
   print ${(l:10::X::Y:)goo} ${(r:10::X::Y:)goo}
  done

打印出相当漂亮的:

  XXXXXXXXYa aYXXXXXXXX
  XXXXXXXYab abYXXXXXXX
  XXXXXXYabc abcYXXXXXX
  XXXXXYabcd abcdYXXXXX
  XXXXYabcde abcdeYXXXX
  XXXYabcdef abcdefYXXX
  XXYabcdefg abcdefgYXX
  XYabcdefgh abcdefghYX
  Yabcdefghi abcdefghiY
  abcdefghij abcdefghij

请注意,这些冒号(可以是其他字符,正如我对 ( s) 和 ( j) 标志所解释的那样)始终成对出现在参数之前和之后,因此对于三个参数,中间的冒号会加倍。你可以错过一部分:Y::X:一部分,看看会发生什么。填充字符串不需要是单个字符;如果它们在填充空间中不适合准确的次数,则最后一次重复将在距插入的参数参数最远的一端被截断。

两个参数告诉 shell 您希望对参数替换的值执行一些特殊操作。 ( P) 标志强制将该值视为参数名称,以便获得双重替换的效果:

  % final=string
  % intermediate=final
  % print ${(P)intermediate}
  string

这有点像$intermediateksh 中所谓的 a nameref,一个被标记为对另一个参数的引用的参数。 Zsh 最终也可能拥有这些;在某些地方,它们比旗帜更方便(P)

更强大的标志是 ( e),它强制重新扫描值以查找所有形式的单字替换。例如,

  % foo='$(print $ZSH_VERSION)'
  % print ${(e)foo}
  4.0.2

重新检查的值$foo,此时找到并执行命令替换。

其余标志是一些简单的特殊格式化技巧:使用 ( o) 按正常词汇(字符)顺序对数组元素进行排序,使用 ( ) 按相反顺序排序,分别使用 ( ) 或 ( )O进行相同的大小写无关,展开提示-用 ( ) 转义(容易记住),像 print 用 p 那样扩展反斜杠转义,用 ( ) 强制所有字符大写或用 ( ) 小写,用 ( ) 大写字符串或每个数组元素的第一个字符,显示特殊字符作为转义序列,带有 ( )。这应该足以继续下去了。oiOi%%ULCV

相关内容