shell 如何检查一个字符串是否是有效的zsh glob模式?

qij5mzcb  于 2023-08-07  发布在  Shell
关注(0)|答案(1)|浏览(124)

我正在编写一个以glob模式作为命令行参数的zsh程序:

tss files --tags 'a*'  # lists files bearing a tag that starts with an 'a'

字符串
为了验证输入,是否有一种方法来检查字符串是否是语法上有效的glob模式?
理想情况下,我将能够验证扩展和非扩展模式,让用户选择使用其中一种,但我希望解决方案只适用于其中一种。

zynd9foi

zynd9foi1#

一种可能性是尝试使用具有${~...}扩展的glob模式。这可以 Package 在一个try-block中,以防止shell在出现错误时退出:

checkGlob() {
  setopt nullglob
  { : ${~1} } always { TRY_BLOCK_ERROR=0 }
}

checkGlob 'aa*'; print $?
# => 0
checkGlob 'aa['; print $?
# => 1

字符串
一些作品

  • setopt nullglob-如果没有匹配的glob模式,则没有错误。
  • { <try-block> } always { <always-block> }-即使 try-block 中有错误,always-block 中的代码也会被执行。
  • :-无操作。将尝试执行随后的扩展,但不会执行任何命令。
  • ${~1}-使用GLOB_SUBST设置扩展第一个位置参数,因此将处理值中的glob模式。
  • TRY_BLOCK_ERROR=0-重置错误状态。通常,运行时错误(如不正确的glob模式)会导致shell退出。这可以防止这种情况。
  • 函数的返回代码来自try块中的最后一个命令,即~扩展。

扩展的glob设置将确定验证哪些glob模式。此版本的函数设置该选项:

checkGlob() {
  setopt nullglob extendedglob localoptions
  pat=APREFIX${1:?}
  {
    : ${~pat} 
  } always {
    TRY_BLOCK_ERROR=0
  } &> /dev/null
}


这也有:

  • localoptions-setopt的更改将仅适用于此函数。
  • pat=APREFIX...-~扩展将尝试在当前目录中查找与模式匹配的实际文件-这是缩短列表的一种方法。另一种选择是切换到用mktemp创建的空目录。
  • &> /dev/null-阻止来自扩展的任何输出。

您可以在关闭扩展的glob的情况下运行类似的检查来尝试这两种类型,但请注意,许多zsh实用程序(如zmv)在默认情况下只是打开扩展的glob,然后就结束了。
测试:

for gl in '*' 'a*' 'a[bc]' 'a[' 'a(.)' 'a(' 'a(#z)' '/tmp'; do
  if checkGlob $gl; then
      print "valid:   $gl"
  else
      print "invalid: $gl"
  fi
done

# => valid:   *
# => valid:   a*
# => valid:   a[bc]
# => invalid: a[
# => valid:   a(.)
# => invalid: a(
# => invalid: a(#z)
# => valid:   /tmp

相关问题