петля через переменную перестала работать

С вашим пересмотренным вопросом, основанным на командной строке, а не на скрипте, самым простым решением будет использование подоболочки для выполнения вашей работы.

например

$ bash
$ x=100
$ echo $x
100
$ exit
$ echo $x

$

Все переменные, которые вы установили между запуском bashи exitэтой оболочки, будут забыты.

Это очень похоже на то, как работает часть wget... | bash, за исключением того, что вы можете вырезать и вставлять/печатать команды.

1
06.12.2020, 13:37
1 ответ

var=value— скалярное присвоение. Он присваивает одно и только одно значение $var. Возможно, вас смутило поведение sh, где это также скалярное присваивание, но, поскольку shне имеет переменных списка/массива, расширение переменных, когда они не заключены в кавычки, подвергается специальной операции split+glob (причина из множество ошибок и проблем с безопасностью в целом и исправлены в большинстве более современных оболочек, включая rc, es, fishилиzsh).

Здесь, поскольку вы хотите сохранить несколько значений, вы хотите использовать переменную массива/списка, а не скалярную переменную.

В 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является надмножеством обеих других команд. Однако awkне очень хорош в извлечении на основе шаблонов -(, если только вы не можете использовать расширения GNU awk). Над этим -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]
3
18.03.2021, 22:45

Теги

Похожие вопросы