如何使自动完成的 systemd 单元名称不区分大小写?

如何使自动完成的 systemd 单元名称不区分大小写?

Bash 自动完成功能对 systemd 单元名称的类似 php 命名约定有很大帮助。彻底解决了Kebab-case、snake_case、camelCase的混合问题。

但我仍然对诸如首字母大小写错误等问题感到沮丧。......t<tab><tab>...sigh...<backspace>T<tab>Thunderbolt甚至B<tab><tab>...sigh...<backspace>b<tab>bluetooth不要让我开始重命名网络管理器:)

我看到bash 完成文件用途systemctl $1 list-units --all "$2*";

最好的方法是什么nocaseglob

答案1

有两种可能性:列出list-units所有单元并稍后在管道中进行 Anycase 匹配,或者将$2*glob 转换为 Anycase glob。

首先,我们将仅显示链接中的当前代码,并重新缩进以便于阅读:

__get_all_units(){
 { __systemctl $1 list-unit-files "$2*"
   __systemctl $1 list-units --all "$2*"
 } |
 { while read -r a b
   do echo " $a"
   done
 }
}

他们可能应该使用printf而不是echo但我们会忽略它。

对于第一个解决方案,删除"$2*"两次,并更改while 循环:

__get_all_units(){
 { __systemctl $1 list-unit-files
   __systemctl $1 list-units --all
 } |
 { shopt -s nocasematch
   while read -r a b
   do if [[ "$a" == $2* ]]
      then echo " $a"
      fi
   done
 }
}

这可行,但在我的系统上相当慢,因为 systemd 在每个单元上做了很多工作。

对于第二个解决方案,创建一个函数来替换 glob 模式(例如 nby )[nN],以便两种情况都匹配。

myanycaseglob(){
 local pat=$1 len=${#1} result i ch
 for i in $(eval echo {0..$(($len-1))})
 do ch=${pat:$i:1}
    if [[ "$ch" == [a-zA-Z] ]]
    then result="$result[${ch,*}${ch^*}]"
    else result="$result$ch"
    fi
 done
 echo "$result"
}

上面的代码使用 bash 将每个字符${ch,*}转换为小写或${ch^*}大写。那么列出匹配项的函数很简单:

__get_all_units() { 
 local anywant=$(myanycaseglob "$2")
 { __systemctl $1 list-unit-files "$anywant*" 
   __systemctl $1 list-units --all "$anywant*"
 } |
 { while read -r a b; do echo " $a"; done; }
}

相关内容