while getopts/case $opt in в bash

На самом деле это единственный раздел про unix на этом форуме

Модератор: /dev/random

kotnaton
Сообщения: 226

while getopts/case $opt in в bash

Сообщение kotnaton » 15.05.2016 10:21

Собственно вопрос в том, что пункт "все прочие" то есть *) Воспринимается как опция -* а не как "все прочие". Можно ли это поправить ?

И второе, как в case можно записать спецсимвол "перевод строки" \n не помогает ?
бывает же такое ???
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 14826
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: while getopts/case $opt in в bash

Сообщение Bizdelnick » 15.05.2016 11:32

Ась?
Код покажите.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
yars
Сообщения: 1143
Статус: Slacker!
ОС: Slackware64-current

Re: while getopts/case $opt in в bash

Сообщение yars » 15.05.2016 15:17

Код: Выделить всё

case $arg in
  a) do_one_action;;
  b) do_another_action;;
  *) true;;
esac

Что тут непонятного?
P.S. А, имеется в виду пример из этой главы ABS. Там встречается case с '-*' и '*' в качестве одного из вариантов выбора. Так звездочка -- это шаблон, удовлетворяющий любой последовательности символов, поэтому и '-[a-z]' совпадет. Потому-то вариант с '*' идет последним.
Slackware64-current/Xfce 4.12/Acer TravelMate 5760
-------------
Registered Linux User #557010
Спасибо сказали:

kotnaton
Сообщения: 226

Re: while getopts/case $opt in в bash

Сообщение kotnaton » 15.05.2016 19:30

Пример:

Код: Выделить всё

while getopts "tsd" opt ;
do
    case $opt in
        t) nm="-t iso9660" ; echo "Опция: -t iso9660"; pause_cd
            ;;
        s) nm="/media/iso" ; echo "Монтируем в /media/iso" ; pause_cd
            ;;
        h) print_help ; exit 0
            ;;
        d) echo "По умолчанию. Без опций" ; pause_cd
        ;;
        *) echo "По-умолчанию"; pause_cd
            ;;
    esac
    udevil mount /dev/sr0 $nm
done


то есть если вызывать mycd без параметров, то пункт *) не задействован. и udevil к "пустышке" не применяется, поэтому и задействован параметр -d. Для того, чтобы запретить "без параметров", надо знать как обозначить. В принципе, конечно, можно избавиться от цикла с getopts и парсить $1, $2, и.т.д. самостоятельно... но так удобнее :)
бывает же такое ???
Спасибо сказали:

Аватара пользователя
yars
Сообщения: 1143
Статус: Slacker!
ОС: Slackware64-current

Re: while getopts/case $opt in в bash

Сообщение yars » 15.05.2016 21:45

Смысл конструкции от меня ускользнул.
Slackware64-current/Xfce 4.12/Acer TravelMate 5760
-------------
Registered Linux User #557010
Спасибо сказали:

kotnaton
Сообщения: 226

Re: while getopts/case $opt in в bash

Сообщение kotnaton » 15.05.2016 22:20

Это каталогизатор имеющихся CD/DVD на сейчас все целиком выглядит так, прошу не бить тапками... Я ведь практически ничего не умею :(

Код: Выделить всё

#!/bin/bash
set -e

function pause_cd() {
eject -t
i=0
until [ $insert_cd ]
    do
        insert_cd=`udisksctl info -b /dev/sr0 | grep Id: | awk '{ print $2 }'`
        sleep 1
        i=$((i+1))
        echo $i
    done
}

function create_tree() {
    f=`df | grep sr0 | awk '{ print $6 }'`
    echo "Метка тома: $old"
    echo $old > tmp
    tree -h $f >> tmp
    rewr=0
    tname="$nnnn"
    while [[ -f $nnnn.list ]]
        do
            rewr=$(($rewr+1))
            tname=$tname"___"$rewr
            if [[ ! -f $tname.list ]]
                then
                    nnnn=$tname
                else
                    tname=$nnnn
            fi
        done
    mv tmp "`echo $nnnn`.list"
    echo "Saved as $nnnn.list"
    if [[ $l = "all" ]] ; then cat "$nnnn.list" ; fi
}

function rename_list() {
    echo "Имя списка: $nnnn"
    echo "Введите новое, или оставьте поле пустым:"
    read r
    if [ $r ]
        then
            old="$nnnn"
            nnnn="$r"
                    echo "Прошли проверку..."
    fi
    echo "Вы ввели: $r , записалось $nnnn"
    old=$nnnn
}

function eject_disc {
    udevil umount /dev/sr0
    eject
    echo "мы дошли до eject"
}


ME=`basename $0`
function print_help() {
    echo "Дополнительные опции"
    echo
    echo "Использование: $ME options..."
    echo "Параметры:"
    echo "  -t          Опция ISO9660 (может понадобиться для некоторых дисков)"
    echo "  -s          Монтирование в директорию /media/iso (нужен для томов с кириллицей и пробелами в названии. Права на директорию 0755 для Users )."
    echo "  -d          По-умолчанию. Без опций."
    echo "  -a          По-умолчанию yes на вопросы."
    echo "  -l        Выводить на экран содержимое готового .list"
    echo "  -h          Справка."
    echo
}

while getopts "tsdla" opt ;
    do
        case $opt in
            t)    nm="-t iso9660"
                echo "Опция: -t iso9660"
                pause_cd
                ;;
            s)    nm="/media/iso"
                echo "Монтируем в точку $nm"
                pause_cd
                ;;
            h)    print_help
                exit 0
                ;;
            d)    echo "По умолчанию. Без опций"
                pause_cd
                ;;
            a)    echo "Вопросов не будет..."
                a="all"
                ;;
            l)    echo "По завершении увидите готовый список"
                l="all"
                ;;
            "")    nm="/media/iso"
                echo "По умолчанию. Без опций"
                pause_cd
                ;;
                *)    nm="/media/iso"
                echo "По-умолчанию"
                pause_cd
                ;;
            esac
        done

if ! mount | grep sr0 ; then udevil mount /dev/sr0 $nm ; fi
nnnn=`echo $( isoinfo -i /dev/sr0 -d | sed '/Volume id: /!d' | sed 's/Volume id: //g')`
rename_list
create_tree
if [[ $a = "all" ]] ; then eject_disc ;
    else
        echo "Ваш диск был вставлен, вынуть ?"
        read r
        case "$r" in
            y|Y|д|Д|""|н|Н)    echo "Вынимаем...";
            eject_disc
            ;;
            n|N|т|Т)    echo "Выходим...";
            udevil umount /dev/sr0
            ;;
        esac
    fi
exit 0
бывает же такое ???
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 14826
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: while getopts/case $opt in в bash

Сообщение Bizdelnick » 15.05.2016 22:29

kotnaton писал(а):
15.05.2016 19:30
getopts может обрабатывать несколько параметров в одной строке ?

Если бы не мог, то какой с него был бы прок? getopts, конечно, может, Ваш скрипт — не может.
Похоже, Вы просто скопировали откуда-то пример и пытаетесь адаптировать его под свои нужды, до конца не поняв, как он работает, угадал? Начните с того, что чётко отделите разбор опций от выполнения полезных действий, тогда код станет яснее:

Код: Выделить всё

# аргументы по умолчанию
nm=

# в цикле — разбор опций
while getopts "tsh" opt; do
    case $opt in
    t)
        nm="$nm -t iso9660"
        echo "Опция: -t iso9660"
        ;;
    s)
        nm="$nm /media/iso"
        echo "Монтируем в /media/iso"
        ;;
    h)
        print_help
        exit 0
        ;;
    esac
done

# теперь — непосредственно полезные действия
pause_cd
udevil mount /dev/sr0 $nm
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

kotnaton
Сообщения: 226

Re: while getopts/case $opt in в bash

Сообщение kotnaton » 12.06.2016 12:52

Bizdelnick

Согласен, поспешил . Я сразу понял что сказал что-то не то. Но вы и не ответили на вопрос, как замотивировать пункт *) для "пустой строки", впрочем судя по этому вопросу на unix.stackexchange.com, штатного решения вопроса попросту нет :(

Если показать echo $opt | od -t c то пустая строка выводит:

Код: Выделить всё

0000000  \n
0000001

бывает же такое ???
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 14826
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: while getopts/case $opt in в bash

Сообщение Bizdelnick » 12.06.2016 23:11

Я правильно понял, что нужно, если не указаны никакие опции, установить $nm в значение по умолчанию? Тогда это элементарно:

Код: Выделить всё

if [ -z "$nm" ]; then
    nm='default value'
fi
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
Vascom
Сообщения: 1332
ОС: Fedora 29

Re: while getopts/case $opt in в bash

Сообщение Vascom » 14.06.2016 14:04

А ещё отсутствие опций в case можно обозначить так:

Код: Выделить всё

"")    echo "По умолчанию. Без опций" ; pause_cd
    ;;

Этот пункт должен идти до пункта со "*".
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 14826
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: while getopts/case $opt in в bash

Сообщение Bizdelnick » 15.06.2016 00:20

Vascom писал(а):
14.06.2016 14:04
отсутствие опций в case можно обозначить так

Нельзя. При отсутствии опций getopts вернёт ненулевой статус, и мы в принципе не попадём в цикл.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

kotnaton
Сообщения: 226

Re: while getopts/case $opt in в bash

Сообщение kotnaton » 17.06.2016 20:11

Всем приятных выходных !

Bizdelnick писал(а):
12.06.2016 23:11
if [ -z "$nm" ]; then


Тогда уж...

Код: Выделить всё

if [ -z $opt ]; then


Спасибо !

Тогда еще схожий, и дурацкий вопрос (и заранее прошу прощения), в целом, если понадобится, свой парсер командной строки, то самое логичное и быстрое состряпать цикл типа:

Код: Выделить всё

i=1; while [[ -z $i -o $i -eq 10 ]] ; do echo $i ; i=$((i+1); done


Беда такого безобразия что переменная $i воспринимается только как переменная $i, а не одна из переменных $1, $2, $3 и.т.д. Допустима ли конструкция типа temp='$'`echo $i`, так чтобы temp содержала не строку текста,а ссылку на одну из переменных командной строки $1, $2, $3 и.т.д. ?
бывает же такое ???
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 14826
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: while getopts/case $opt in в bash

Сообщение Bizdelnick » 17.06.2016 20:29

kotnaton писал(а):
17.06.2016 20:11
самое логичное и быстрое состряпать цикл типа:

Код: Выделить всё

while [ $# -gt 0 ]; do
    echo "$1"
    shift
done

Upd. Или так:

Код: Выделить всё

for arg; do
    echo "$arg"
done
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

kotnaton
Сообщения: 226

Re: while getopts/case $opt in в bash

Сообщение kotnaton » 21.11.2018 09:46

Можно ли в getopts заменить дефис каким либо другим символом или сделать незначащим ?. К примеру, чтобы синонимом команды j -a -b -c -d можно было запустить и так: j abcd, и (или) так j /abcd
бывает же такое ???
Спасибо сказали:

Аватара пользователя
Vascom
Сообщения: 1332
ОС: Fedora 29

Re: while getopts/case $opt in в bash

Сообщение Vascom » 21.11.2018 09:49

Нет. А зачем?
Обычно можно так
Спасибо сказали: