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 模式(例如
n
by )[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; }
}