制作两个列表,匹配和不匹配特定的文件类型

制作两个列表,匹配和不匹配特定的文件类型

我有一个 bash 函数,其参数是文件。因此,以下打印语句给出

opts="$@"
echo "$fargs"

Result:
linge-cellar.rc linge-cellar.rc~ linge-checkn.rc linge-checkn.rc~ linge-comint.rc linge-comint.rc~ linge-comseq.rc linge-comseq.rc~ linge-console.rc linge-console.rc~ linge-curiplaya.rc linge-curiplaya.rc~ linge-dircolors.rc linge-dircolors.rc~ linge-firefly.rc linge-firefly.rc~ linge-mosaic.rc linge-mosaic.rc~ linge-profile.rc opcon-cellar.rc~

我有两个数组inclexcl用于存储要处理的文件类型。

Example: incl=( .rc )

我想要创建两个列表。一个列表包含与数组中的文件类型匹配的文件 incl(例如,带有.rc扩展名的文件)。另一个列表包含文件类型不匹配的文件名(例如,带有扩展名的文件.rc~)。

从一个简单的循环开始

  fargs="$@"
  local f ty aggr=()
  for f in $fargs; do
    for ty in "${incl[@]}"; do
      [[ "$f" =~ *${ty}$ ]] && aggr+=( "$f" )
    done
  done  

  echo "$fargs"

  echo
  echo "${incl[@]}"

  echo
  echo " aggr:"
  echo " ${aggr[*]}"
  

但有些不对劲,因为我总是得到一个空aggr数组。

dvorak linge-cellar.rc linge-cellar.rc~ linge-checkn.rc linge-checkn.rc~ linge-comint.rc linge-comint.rc~ linge-comseq.rc linge-comseq.rc~ linge-console.rc linge-console.rc~ linge-curiplaya.rc linge-curiplaya.rc~ linge-dircolors.rc linge-dircolors.rc~ linge-firefly.rc linge-firefly.rc~ linge-mosaic.rc linge-mosaic.rc~ linge-profile.rc opcon-cellar.rc~

.rc

 aggr:

答案1

主要问题是您将正则表达式语法($行锚点)与 glob 模式语法(前导*通配符)混合在一起,您可以通过一个简单的测试来验证:

$ ty=.rc; [[ foo.rc =~ *${ty}$ ]] ; echo $?
2 

(语法有效测试的退出状态应该是 0 或 1)。

您的测试可以是

[[ "$f" =~ ${ty}$ ]]    # regex

或者

[[ "$f" = *${ty} ]]     # glob pattern

同样,fargs="$@"是标量赋值;for f in $fargs然后,不带引号的变量会在空格处拆分 (string) 变量 - 如果任何文件名包含空格,则会中断。您应该使用fargs=("$@")然后for f in "${fargs[@]}"。或者,直接循环遍历位置参数,或者for f in "$@",POSIXLY,只需for f

#!/bin/bash

myfunc () {

  local f ty aggr=()
  for f do
    for ty in "${incl[@]}"; do
      [[ "$f" = *${ty} ]] && aggr+=( "$f" )
    done
  done

  printf '%s\n' "${aggr[@]}"
}

incl=( .rc )

myfunc linge-cellar.rc linge-cellar.rc~ linge-checkn.rc linge-checkn.rc~ \
       linge-comint.rc linge-comint.rc~ linge-comseq.rc linge-comseq.rc~ \
       linge-console.rc linge-console.rc~ linge-curiplaya.rc linge-curiplaya.rc~ \
       linge-dircolors.rc linge-dircolors.rc~ linge-firefly.rc linge-firefly.rc~ \
       linge-mosaic.rc linge-mosaic.rc~ linge-profile.rc opcon-cellar.rc~

测试:

$ ./myscript
linge-cellar.rc
linge-checkn.rc
linge-comint.rc
linge-comseq.rc
linge-console.rc
linge-curiplaya.rc
linge-dircolors.rc
linge-firefly.rc
linge-mosaic.rc
linge-profile.rc

在 zsh 中,可以通过${name:#pattern}对位置参数数组应用参数扩展来避免内部循环,并使用M修饰符删除不匹配的元素(默认情况下,不带M,会删除匹配的元素):

#!/bin/zsh

myfunc () {

  local ty aggr=()

  for ty in ${incl[@]}; do
    aggr+=( ${(M)@:#*${ty}} )
  done

  print -rC1 ${aggr[@]}
}

参见此类似的 Unix 和 Linux 答案有没有一种简单的方法来获取所有不以连字符开头的参数的数组?

相关内容