LINUX.ORG.RU

Bash-скрипт и параметры

 ,


2

1

Привет!

Есть скрипт, который сейчас получает параметры так:

./script.sh -a -b -c -n --file filename

Хочется такого:

./script.sh -abc -n --file filename

Как такое можно организовать? В Интернетах могу найти только первый вариант.

Заранее огромное спасибо!

P.S. И, да, желательно обойтись без установки дополнительного софта или изменения существующего - интересует именно реализация этого в самом скрипте.

Пока в порядке велосипеда придумал лишь проверку - если есть два минуса - обрабатывать как целый параметр, один минус - каждый символ отдельно. Есть более правильные варианты?

alozovskoy ★★★★★ ()
Ответ на: комментарий от alozovskoy

Ссылка там, конечно не совсем по теме, но таки ответ на то, как сделать - есть: использовать утилиту getopt. Вот листинг примера её использования.

#!/bin/bash

# A small example program for using the new getopt(1) program.
# This program will only work with bash(1)
# An similar program using the tcsh(1) script language can be found
# as parse.tcsh

# Example input and output (from the bash prompt):
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
# Option a
# Option c, no argument
# Option c, argument `more'
# Option b, argument ` very long '
# Remaining arguments:
# --> `par1'
# --> `another arg'
# --> `wow!*\?'

# Note that we use `"$@"' to let each command-line parameter expand to a 
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
     -n 'example.bash' -- "$@"`

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
        case "$1" in
                -a|--a-long) echo "Option a" ; shift ;;
                -b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
                -c|--c-long) 
                        # c has an optional argument. As we are in quoted mode,
                        # an empty parameter will be generated if its optional
                        # argument is not found.
                        case "$2" in
                                "") echo "Option c, no argument"; shift 2 ;;
                                *)  echo "Option c, argument \`$2'" ; shift 2 ;;
                        esac ;;
                --) shift ; break ;;
                *) echo "Internal error!" ; exit 1 ;;
        esac
done
echo "Remaining arguments:"
for arg do echo '--> '"\`$arg'" ; done
Выполняем:
$ bash /usr/share/getopt/getopt-parse.bash -a -b asd
Option a
Option b, argument `asd'
Remaining arguments:
$ bash /usr/share/getopt/getopt-parse.bash -ab asd
Option a
Option b, argument `asd'
Remaining arguments:
$ bash /usr/share/getopt/getopt-parse.bash -a --b-long asd
Option a
Option b, argument `asd'
Remaining arguments:

shell-script ★★★★★ ()
Ответ на: комментарий от shell-script

Нет, он обрабатывает некорректно - приходится соблюдать порядок символов, иначе в случае "-ba args" «b» считает своим аргументом «a», «a» не обрабатывается и т.д.

alozovskoy ★★★★★ ()
Ответ на: комментарий от alozovskoy

Это интересно какая программа умеет так телепатически аргументы парсить? Вот, для примера, первая попавшаяся утилита:

$ ls -R
.:
file1  file2  somedir

./somedir:
file4
$ ls -aI somedir
.  ..  file1  file2  .file3
$ ls -Ia somedir
file4

Она тоже некорректно работает?

shell-script ★★★★★ ()
Ответ на: комментарий от shell-script
$ ( echo "TEST"; echo "ololo"; echo "testololo" ) | grep -iw test 
TEST
$ ( echo "TEST"; echo "ololo"; echo "testololo" ) | grep -wi test 
TEST

То есть тут все равно, как указать параметры, один из которых не требует значения - второй корректно прочитает свое значение.

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

Вот более наглядный пример

$ ( echo "TEST"; echo "ololo"; echo "test ololo" ) | grep -wi test
TEST
test ololo

$ ( echo "TEST"; echo "ololo"; echo "test ololo" ) | grep -iw test
TEST
test ololo
alozovskoy ★★★★★ ()
Ответ на: комментарий от alozovskoy

grep в любом случае требует паттерна. Опции -w, -e, -E и т.д. по сути меняют режим обработки паттерна или вывода результата. test не является аргументом опции -w.

shell-script ★★★★★ ()

Набыдлокодил специально для тебя:

#!/bin/bash

for data in $@; do
    [ "${data:0:1}" == "-" ] && {
        count=$(( $(echo "$data" | wc -m) - 1 ))
        while [ "$(($count - 1))" != "0" ]; do
            echo -n "dbg:option: ${data:$(($count - 1)):1} > "
            count=$(($count - 1))
            case ${data:$(($count - 1)):1} in
                "a" )
                echo "hello1" ;;
                "b" )
                echo "hello2" ;;
                *)
                echo "bad command" ;;
            esac
        done
    }
done
┌[lord] [home-hell-machine]:~ 
└>./test_d.sh -abc -b
dbg:option: c > hello2
dbg:option: b > hello1
dbg:option: a > bad command
dbg:option: b > bad command

Spirit_of_Stallman ★★★ ()
Ответ на: комментарий от alozovskoy

Но спасибо за участие!!

Та нету за что, общество и всё такое :)
И оставлю тут версию без косяка, если таки кому-то еще нужно будет:

#!/bin/bash

for data in $@; do
    [ "${data:0:1}" == "-" ] && {
        count=$(( $(echo "$data" | wc -m) - 1 ))
        while [ "$(($count - 1))" != "0" ]; do
            echo -n "dbg:option: ${data:$(($count - 1)):1} > "
            case ${data:$(($count - 1)):1} in
                "a" )
                echo "hello1" ;;
                "b" )
                echo "hello2" ;;
                *)
                echo "bad command" ;;
            esac
            count=$(($count - 1))
        done
    }
done

Spirit_of_Stallman ★★★ ()

В моем древнем быдлокоде, я сделал как-то так(просто скопипастю): тыц
Вижу уже опоздал, и тема закрыта. Решайте сами что с этим делать.

nexfwall ★★★★ ()
Последнее исправление: nexfwall (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.