ループ変数が動作を停止しました。

ループ変数が動作を停止しました。

外部USBキーボードが接続されると、別のレイアウトを割り当てるアクションシェルスクリプトがありますが、もう機能しません。 shからzshに切り替えたからかわかりません。

usbkbd_id="$(xinput -list | grep "USB Keyboard" | awk -F'=' '{print $2}' | grep "keyboard" | cut -c 1-2)"
for ID in $usbkbd_id; do
    setxkbmap -device ${ID} -layout "es"
done

コマンドで確認してみると、echo "device: ${ID} layout: ${usbkbd_layout}" >> test.txt実際に各IDを繰り返すことなく、最初の変数全体の出力の先頭に「device:」だけを追加したことがわかりました。

同様の質問と回答があり、${usbkbd_id[@]}初級レベルのスクリプト技術を使用して他の代替案を試しましたが、それを理解することはできません。

実際、問題の実際の原因は、外部USBキーボードに対して常に3つのIDを取得し、実際にそのうちの1つだけがキーボードレイアウトを割り当てるのに機能しますが、どちらがわからないことです。したがって、このコマンドは動作する場合もあり、動作しない場合もあります(正しいIDが最後のIDではない場合)。

答え1

var=valueスカラー割り当てです。それは割り当てる一つ値が1つしかありません$varshスカラー割り当てと呼ばれる動作のために混乱する可能性がありますが、shリスト/配列変数がないため参照されていない場合、変数拡張は特別な分割+glob操作を受けます。全体的にバグやセキュリティの問題がたくさんあります。rc、または)esを含むほとんどの最新のシェルで修正されました。fishzsh

ここでは複数の値を保存したいので、スカラー変数の代わりに配列/リスト変数を使用したいと思います。

では、zsh配列変数の割り当ては次のように行われます。

var=( values )

通事論。

だから:

usbkbd_ids=(
  $(xinput list | grep -Po 'USB Keyboard.*id=\K\d+(?=.*keyboard)')
)
for id in $usbkbd_ids; do
    setxkbmap -device $id -layout es
done

ここでは、次のようにすることもできます。

xinput list |
  grep -Po 'USB Keyboard.*id=\K\d+(?=.*keyboard)' |
  xargs -I ID setxkbmap -device ID -layout es

awkを使用する必要はほとんどなく、grep一緒cutに使用すると、awk他の2つのコマンドの親セットです。しかし、awkパターンベースの抽出にはあまり良くありません(GNUawk拡張が利用できない場合)。上記-Pは非標準grep拡張です。標準的な代替として、以下を使用できますsed

  xinput list |
    sed -n 's/^.*USB Keyboard.*id=\([0-9]*\).*keyboard.*/\1/p'

標準のawk場合は次のとおりです。

xinput list |
  awk '/USB Keyboard.*id=.*keyboard/ && match($0, /id=[0-9]+/) {
         print substr($0, RSTART + 3, RLENGTH - 3)
       }'

zsh次の独自のパターン抽出機能を使用することもできます。

usbkbd_ids=()
for line (${(f)"$(xinput list)"})
  [[ $line =~ 'USB Keyboard.*id=([0-9]+).*keyboard' ]] &&
    usbkbd_ids+=$match[1]

関連情報