Kus*_*nda 4 zsh wildcards random
随着水珠预选赛中的zsh
一个可以在文件名以各种方式通配符模式匹配的结果进行排序。例如,该模式*(om)
将匹配当前目录中的所有非隐藏名称,按修改时间戳排序。
但是,我有时希望有一种随机排序的方法(例如,获取文件的随机抽样)。据我所知,没有限定符可以直接执行此操作。
问题:如何从zsh
文件名通配模式中获取随机的路径名列表?
使用随机排序键(全局限定符 oe
)::
*(Noe\''REPLY=$RANDOM,$RANDOM'\')
Run Code Online (Sandbox Code Playgroud)
解释:
oe
后跟一个字符分隔符、一段代码和另一个分隔符。代码块可能不包含分隔符。特殊字符需要进行转义,以便在解析 glob 限定符本身时不会解析它们。'
作为分隔符(使用反斜杠,因为它需要转义),并且我用代码包装'
以保护可能存在的特殊字符。这样我就可以编写任意代码,只要它不包含'
.REPLY
最初设置为文件名,并且任何代码设置REPLY
为用作排序键)。要$n
随机采样元素,请添加[…]
限定符:
*(Noe\''REPLY=$RANDOM,$RANDOM'\'[1,$n])
Run Code Online (Sandbox Code Playgroud)
有时,某些元素会获得相同的排序键,因此所有排列的可能性并不相同,稍微倾向于保留将排序函数应用于按目录顺序的列表¹ 的任何结果,但偏差很小。我$RANDOM,$RANDOM
用作排序键而不是$RANDOM
减少偏差:$RANDOM
是一个 15 位数字,当文件数量接近 2^15 时,偏差会很明显。
请注意,$RANDOM
如果轻微的偏差不是问题,这对于采样来说已经足够了。它不适合任何涉及安全的事情。如果您想要安全的随机排列,请使用 GNU coreutils 的shuf
. (如果您最喜欢的操作系统缺少本机,shuf
并且您出于某种原因不想安装 GNU coreutils,则可以尝试使用ibara 的重新实现。)
securely_permuted=("${(0)$(printf '%s\0' *(N) | shuf -z))}")
Run Code Online (Sandbox Code Playgroud)
或更简单的版本,可能会遇到命令行长度限制:
securely_permuted=("${(0)$(shuf -z -- *(N)))}")
Run Code Online (Sandbox Code Playgroud)
¹实验上,排序是稳定的(例如*(omoe\''REPLY=1'\')
,相当于*(om)
,但顺序*(oe\''REPLY=1'\')
不匹配*(oN)
。无论如何,这是有利于某些特定顺序的小偏差。
归档时间: |
|
查看次数: |
311 次 |
最近记录: |