Вопрос или проблема
Я работаю над установочным скриптом для программы, которая нуждается в идентификаторе устройства из lsusb в своей конфигурации, поэтому я подумал сделать следующее:
$usblist=(lsusb)
# помещаем список в массив для каждой строки.
# используем массив, чтобы предоставить пользователю список выбора с помощью whiptail.
# из этой строки извлекаем идентификатор устройства и идентификатор поставщика из выбранной строки.
Строка выглядит следующим образом:
Bus 001 Device 004: ID 0665:5161 Cypress Semiconductor USB to Serial
Мне нужны только 9 символов после “ID{пробел}”
Первые ошибки, которые я вижу, это. Вы написали $usblist=(lsusb | awk '{print $6}')
Вам нужно убрать $
в начале и добавить $
перед (
. Некоторые кавычки также будут полезны. То есть:
usblist="$(lsusb | awk '{print $6}')"
Просто используйте это, здесь используется awk
для вывода 6-го
поля, который в вашем случае является идентификатором устройства.
usblist="$(lsusb | awk '{print $6}')"
Таким образом, вы можете вывести любое поле, которое хотите, вот сопоставление:
- $1 : Bus
- $2 : 001
- $3 : Device
- $4 : 004:
- $5 : ID
- $6 : 0665:5161
- $7 : Cypress
- $8 : Semiconductor
- $9 : USB
- $10 : to
- $11 : Serial
Если вы хотите вывести более одного поля, например, имя, вы можете сделать так:
usblist="$(lsusb | awk '{print $7,$8,$9}')"
usblist=
lsusb | awk '{print $6}'
echo $usblist
Это должно вывести 0665:5161, кроме awk
вы также можете использовать команду cut. Ознакомьтесь с мануалом cut для получения дополнительной информации.
Синтаксис присваивания массивов в zsh, ksh93, bash, mksh или yash выглядит так:
array=( value1 value2... )
Получить вывод команды можно с помощью $(команда)
.
Разделение вывода команды по новому ряду можно сделать с помощью параметра расширения f
в zsh
или в других оболочках, оставив $(...)
без кавычек (оператор разделения+глоб). Это возможно после присваивания символа новой строки специальной переменной $IFS
и отключения глобирования.
-
zsh
:array=( ${(f)"$(команда)"} )
-
другие оболочки (но также и zsh)
IFS=' ' set -o noglob # не требуется в zsh, если не в эмуляции sh/ksh array=( $(команда) )
Чтобы получить 6й делитель, разделенный пробелами, из каждой строки вывода команды, как и говорили другие, вы можете использовать awk '{print $6}'
или grep -Po '^.*?ID \K.{9}'
(при условии, что используется GNU grep
или совместимый с поддержкой регулярных выражений в стиле perl), чтобы получить девять символов после первого вхождения ID<пробел>
, как вы и запросили. Таким образом, собрав все вместе, это выглядит так:
array=( ${(f)"$(lsusb | awk '{print $6}')" ) # (zsh)
IFS='
'
set -o noglob
array=( $(lsusb | awk '{print $6}') )
Теперь, если $IFS
по умолчанию содержит пробел, табуляцию, новую строку (и NUL в zsh), идентификаторы USB теоретически содержат только шестнадцатеричные цифры и двоеточия, поэтому вывод awk
должен гарантированно не содержать пробелов, табуляций, нулей и глобирующих символов, поэтому, если вы можете гарантировать, что $IFS
все еще содержит свое значение по умолчанию, вы можете пропустить первые две команды и упростить это до:
array=( $(lsusb | awk '{print $6}') )
Или вы можете получить информацию напрямую из /sys
без необходимости использовать lsusb
или awk
в zsh
с помощью:
array=(
/sys/bus/usb/devices/*/idVendor(Ne['REPLY=$(<$REPLY):$(<$REPLY:h/idProduct)'])
)
Используя глобальное расширение для нахождения файлов idVendor
и квалификатор e
глоб для замены каждого расширения глоба содержимым этого файла и содержимым файла idProduct
в той же директории (также имеет преимущество в виде упорядоченного списка).
Ответ или решение
Для получения идентификатора устройства из вывода команды lsusb
на основе пользовательского ввода в скрипте установки, вы можете использовать следующие шаги. Будем использовать awk
для обработки вывода команды lsusb
, а также whiptail
для отображения списка доступных устройств.
Ниже представлен пример скрипта, который демонстрирует весь процесс:
#!/bin/bash
# Получаем список USB-устройств и извлекаем идентификаторы устройств
usblist=($(lsusb | awk '{print $6}'))
# Отображаем диалоговое окно с выбором устройства
selected_device=$(whiptail --title "Выберите USB устройство" --menu "Доступные устройства:" 15 60 10 "${usblist[@]}" 3>&1 1>&2 2>&3)
# Проверяем, выбрано ли устройство
exitstatus=$?
if [ $exitstatus != 0 ]; then
echo "Отмена выбора." >&2
exit 1
fi
# Выводим выбранный идентификатор устройства
echo "Вы выбрали идентификатор устройства: $selected_device"
Объяснение
-
Получение идентификаторов USB-устройств:
Командаlsusb
возвращает список всех подключенных USB-устройств. С помощьюawk '{print $6}'
мы извлекаем значения, которые находятся в шестом поле (это и есть идентификаторы устройства в форматеvendor_id:product_id
). -
Создание массива:
С помощьюusblist=($(lsusb | awk '{print $6}'))
мы сохраняем идентификаторы устройства в массивusblist
, который может затем быть использован в диалоговом окне. -
Использование
whiptail
:
Командаwhiptail
создает графическое меню, позволяющее пользователю выбрать одно из USB-устройств. Параметры15 60 10
определяют размеры окна и количество строк для выбора. -
Проверка выбора:
Проверяем, был ли сделан выбор. В случае, если пользователь закроет меню или отменит выбор, выводится сообщение об ошибке и скрипт завершается. -
Вывод результата:
После успешного выбора выводится идентификатор устройства.
Дополнительные замечания
- Убедитесь, что
whiptail
установлен на вашей системе. Это можно сделать с помощью пакетного менеджера вашего дистрибутива. - Этот пример предполагает, что у вас есть доступ к командной строке bash и необходимые права для выполнения команды
lsusb
. - Если вам нужно извлечь дополнительные данные о выбранном устройстве (например, производитель), вы можете модифицировать скрипт для этого.
Заключение
Этот скрипт должен помочь вам в автоматизации процесса выбора устройства USB и извлечения его идентификатора для дальнейшей настройки конфигурации вашего программного обеспечения.