オートコンプリートシステムユニット名を大文字と小文字を区別しないようにする方法は?

オートコンプリートシステムユニット名を大文字と小文字を区別しないようにする方法は?

Bashオートコンプリートは、システムユニット名のPHPに似た命名規則に多くの役に立ちます。 Kebab-case、snake_case、camelCaseの混在問題を完全に解決しました。

しかし、最初の文字の間違った大文字の使用のような問題のため、まだ欲求不満を感じます。 ...t<tab><tab>...sigh...<backspace>T<tab>Thunderboltそして、B<tab><tab>...sigh...<backspace>b<tab>bluetoothネットワーク管理者の名前を変更しないでください:)

私は見たバッシュ完了ファイル使用systemctl $1 list-units --all "$2*";

最良のアプローチは何ですかnocaseglob

答え1

2つの可能性があります。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*"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は各デバイスで多くの操作を実行するため、私のシステムではかなり遅いです。

2番目の回避策では、両方のケースが一致するようにglobパターンを置き換える関数(たとえば n)を作成します。[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; }
}

関連情報