LINUX.ORG.RU

Странный вывод строки в whiptail

 ,


0

1

Всех приветствую. Пишу скрипт и столкнулся с проблемой. Сам скрипт:

#!/bin/bash
clear
        drivelist=$(lsblk --nodeps --noheadings --output NAME,SIZE)
        drivesize=($(lsblk --nodeps --noheadings --output SIZE))
        count_drivers=$(lsblk --nodeps --noheadings --output NAME | wc -l)
z=1
while [ $z -lt $((count_drivers+1)) ]
      do[br]
        disks=($(echo -e "$drivelist"))
        z=$(( $z + 1 ))
       done
OPTION=$(whiptail --title "Диски" --menu "Выберите диск" 15 60 4  "${disks[@]}" 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
echo "$OPTION"
else
echo "Вы нажали отмену."
fi

При таком коде все выполняется нормально. Скриншот - https://ibb.co/Npt5MJr Если немного изменить строку с

drivelist=$(lsblk --nodeps --noheadings --output NAME,SIZE)

на

drivelist=$(lsblk --nodeps --noheadings --output NAME,SIZE,MODEL)

то в самом меню отображение модели диска уходит на след. строку. Скриншот - https://ibb.co/NtL1jx1 Можно ли это поправить?

И вопрос номер два, есть ли инструменты автоматического присвоения номера диску в списке меню?


Ответ на: комментарий от Dataon

Ну, разбирайся тогда. В общем, когда ты данные в массив загоняешь и отдаешь whiptail’у, то в итоге получаешь один аргумент - весь массив одной строкой. А ему надо «arg1» «arg2» «arg3» и т.д. А также надо отсекать нужные пункты обратным слэшем \

gnu_linux
()
Последнее исправление: gnu_linux (всего исправлений: 1)
Ответ на: комментарий от Dataon

В общем, посмотрел я это чудо консоли) Слэш нужен только для удобочитаемости, когда с переносами строки кодишь, вот так:

whiptail --title  "меню" --menu  "выбор" 15 60 4 \
"Пункт 1" \
"Пункт 2" \
"и т.д. " 3>&1 1>&2 2>&3
Когда в одну строку можно без слэша соответственно:
whiptail --title  "меню" --menu  "выбор" 15 60 4 "Пункт 1" "Пункт 2" "и т.д. "
дальше, чтоб нумерация была, перед аргументом просто цифру в кавычках надо:
whiptail --title  "меню" --menu  "выбор" 15 60 4 "1" "Пункт 1" "2" "Пункт 2" "3" "и т.д. "
дальше надо упростить код для начала:
drivelist=$(lsblk --nodeps --noheadings --output NAME,SIZE)
drivesize=($(lsblk --nodeps --noheadings --output SIZE))
count_drivers=$(lsblk --nodeps --noheadings --output NAME | wc -l)
disks=($(echo -e "$drivelist"))
Заменить всё это на одну строку, например:
lsblk --nodeps --noheadings --output NAME,SIZE,MODEL | nl
Даст вот такой нумерованный список:
1  sda  126,9G KINGSTON SVP200S
2  sdb  250,2G m.2 Smartbuy S11
а дальше опять думать)

gnu_linux
()
Последнее исправление: gnu_linux (всего исправлений: 1)
Ответ на: комментарий от gnu_linux

Попробовал многое, и ничего не получается (вероятно мешает природная тупость).

Пробовал менять echo на printf - результат такой-же.

Складывается впечатление что при выводе в whiptail срабатывает какой-то перенос строки.

Еще заметил что содержимое переменной $disks выравнивается по ширине, может это как-то влияет?

Искал и не смог найти выравнивание текста в самом whiptail. Думаю что все таки смотреть нужно в сторону выравнивания текста.

Продолжаю экспериментировать…


Попробовал пойти другим путем: заменил

lsblk --nodeps --noheadings --output NAME,SIZE

вывод:

/dev/sda 146Gb

на

fdisk -l | grep 'Disk /dev' | sed 's|.*/dev/||' | sed -r 's/(.+GB).+/\1/'

вывод:

/dev/sda 146 Gb

и снова перенос строки, и самое интересное получается как только в строке переменной $disks присутствует третий столбец(значение после второго пробела в строке) , в whiptail происходит перенос строки.

Dataon
() автор топика
Последнее исправление: Dataon (всего исправлений: 2)

Вот лови как ты хотел:

#! /bin/bash
#
clear

IFS=$'\n' 

disks=($(printf 'Диск:\n%s\n' $(lsblk -o NAME,SIZE,MODEL | grep -wE sd[a-z])))

whiptail --title  "Диски" --menu  "Выберите диск" 25 100 12 "${disks[@]}" 3>&1 1>&2 2>&3

#
exit 0
Rx0
()
Последнее исправление: Rx0 (всего исправлений: 1)
Ответ на: комментарий от Rx0

Читать тут - BASH - Внутренние переменные

$IFS
разделитель полей во вводимой строке (IFS -- Input Field Separator)

По-умолчанию -- пробельный символ (пробел, табуляция и перевод строки), но может быть изменен, например, для разбора строк, в которых отдельные поля разделены запятыми. Обратите внимание: при составлении содержимого переменной $*, Bash использует первый символ из $IFS для разделения аргументов. См. Пример 5-1.

bash$ echo $IFS | cat -vte
$


bash$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z
             


Caution	
При всем при том следует помнить, что при использовании $IFS пробельные символы обрабатываются несколько иначе, чем все остальные.

Пример 9-1. $IFS и пробельные символы

#!/bin/bash
# При использовании $IFS, пробельные символы обрабатываются иначе, чем все остальные.

output_args_one_per_line()
{
  for arg
  do echo "[$arg]"
  done
}

echo; echo "IFS=\" \""
echo "-------"

IFS=" "
var=" a  b c   "
output_args_one_per_line $var  # output_args_one_per_line `echo " a  b c   "`
#
# [a]
# [b]
# [c]


echo; echo "IFS=:"
echo "-----"

IFS=:
var=":a::b:c:::"               # То же самое, только пробелы зменены символом ":".
output_args_one_per_line $var
#
# []
# [a]
# []
# [b]
# [c]
# []
# []
# []

# То же самое происходит и с разделителем полей "FS" в awk.

# Спасибо Stephane Chazelas.

echo

exit 0
Rx0
()
Ответ на: комментарий от Rx0

В общем после введения IFS получилось ровно наоборот. Теперь гад в одну строку выводит.

Вот код:

#!/bin/bash
clear
       drivelist=$(fdisk -l | grep 'Disk /dev' | sed 's|.*/dev/||' | sed -r 's/(.+GB).+/\1/')
       count_drivers=$(lsblk --nodeps --noheadings --output NAME | wc -l)
z=1
while [ $z -lt $((count_drivers+1)) ]
      do
        IFS=$'\n' disks=($(echo -e "$drivelist"))
        z=$(( $z + 1 ))
       done
OPTION=$(whiptail --title "Диски" --menu "Выберите диск" 15 70 3 "${disks[@]}" 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
echo "$OPTION"
else
echo "Вы нажали отмену."
fi
Dataon
() автор топика
Ответ на: комментарий от Dataon

Теперь гад в одну строку выводит.

Это не мой скрипт. У меня все выводит правильно. )

Ты очень странный «кекс». ) Тебе дают готовое решение, а ты снова продолжаешь «жрать кактус»… )))

Rx0
()

Добрый день! Интересуюсь возможностью перепрошивки дисков IBM. В одной из архивных тем вы писали, что вам известна процедура «шитья». Она бы мне очень помогла. Подскажите, сможете ли вы помочь и поделиться ей? СХД IBM V5000 Извиняюсь за оффтоп, но та тема уже в архиве :)

Unortodox
()
Ответ на: комментарий от Rx0

Если «готовое» решение не работает сразу на двух моих машинах, на двух разных версиях Ubuntu, значит оно не совсем работает у меня, а это в свою очередь заставляет меня обращаться к вам уважаемые форумчане за помощью. А не ходить в магазин хлебобулочных изделий.

Dataon
() автор топика
Ответ на: комментарий от Unortodox

К сожалению порадовать пока ничем не могу, проект забросил, на днях начал снова его возвращать, так что если появятся успехи конечно поделюсь опытом. Даже если он будет отрицательным.)

Dataon
() автор топика
Ответ на: комментарий от Rx0

Итак, Ваш скрипт доработал немного. (диски не всегда имеют имена sda,sdb и т.д. А могут например называться cciss/c0d0, cciss/c1d0 и т.д.)

Скрипт работает, однако мне не нужно чтобы перед каждой строкой было слово «Диск» так как далее значение выбранной строки при выборе передается переменной $OPTION.

И если стоит впереди слово «Диск» то значение переменной всегда будет «Диск», а мне необходимо что бы было имя выбранного диска (sda,sdb,cciss/c0d0 и т.д.)

#! /bin/bash
clear

IFS=$'\n'
disks=($(printf "Диск:\n%s\n" $(lsblk -o NAME,SIZE,MODEL | grep -wE "c[0-9]d0|sd[a-z]")))
OPTION=$(whiptail --title  "Диски" --menu  "Выберите диск" 25 80 12 "${disks[@]}" 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
echo "$OPTION"
else
echo "Вы нажали отмену."
fi
exit 0

Почитал про синтаксис printf поменял с «Диск\n%s\n» на «%s\n» но результата это не дало, в меню снова все в одну строку.

Может где нужно еще воткнуть перенос строки?

Dataon
() автор топика
Ответ на: комментарий от Dataon

Может где нужно еще воткнуть перенос строки?

Самостоятельно. :)

Rx0
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.