Автор Гілка: Тренінг по bash. Урок 1.  (Прочитано 8272 раз)

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3820
  • Карма: +11/-0
  • Програміст
Re: Тренінг по bash. Урок 1.
« Відповідей #15 : 2007-10-01 22:28:55 »

Ось мій приклад розбору командного рядка на bash-і:
#!/bin/bash

# Treat unset variables as an error when substituting.
set -u

# Define some variables
SOME_VAR="no"
SOME_VAR_WITH_VALUE="default value"

# Print help message when no arguments are passed to script
if [ "$#" -eq 0 ]
then
  pod2usage -verbose 1 "$0"
  exit 1
fi

# Parse arguments
while [ $# -gt 0 ]
do
  case "$1" in
    --help|-h|-\?)
      pod2usage -verbose 1 "$0"
      exit 0
    ;;

    --man)
      pod2usage -verbose 2 "$0"
      exit 0
    ;;
    
    --test|-t)
      SOME_VAR="yes"
      shift # Discard option from list of arguments
    ;;
  
    --test-arg|-T)
      SOME_VAR_WITH_VALUE="${2?Argument is required.}"
      shift 2 # Discard option and it argument
    ;;
    
    --)
      # Rest of command line arguments are non option arguments
      shift # Discard separator from list of arguments
      break # Finish for loop
    ;;
  
    -*)
      echo "Unknown option: $1" >&2
      pod2usage -verbose 1 --output ">&2" "$0"
      exit 2
    ;;
    
    *)
      # Non option argument
      break # Finish for loop
    ;;
  esac
done

# Program body
echo "SOME_VAR: $SOME_VAR."
echo "SOME_VAR_WITH_VALUE: \"$SOME_VAR_WITH_VALUE\"."
echo "Arguments: $@"

exit 0

__END__

=pod

=head1 NAME

sample - example of command line parsing

=head1 SYNOPSIS

sample [OPTIONS] [ARGUMENTS]

=head1 OPTIONS

=over 4

=item B<--help> | B<-h>

Print a brief help message and exits.

=item B<--man>

Prints the manual page and exits.

=item B<--test> | B<-t>

Set SOME_VAR to "yes".
  
=item B<--test-arg> | B<-T> ARGUMENT

Set value of SOME_VAR_WITH_VALUE.

=back

=head1 DESCRIPTION

B<This program> is example of command line arguments parsing.

=head1 AUTHOUR

Volodymyr M. Lisivka <vlisivka@gmail.com>

=cut

Основні моменти:
  • Використовується найпростіший варіант: --КЛЮЧ, або -К, або --КЛЮЧ ЗНАЧЕННЯ, або -К ЗНАЧЕННЯ. Варіант -КККК не підтримується;
  • для виводу довідки використовується pod2usage з perl;
  • man-сторінка може бути згенерована з тіла скрипта командою pod2man;
  • код простий як двері.
[Fedora Linux]

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3820
  • Карма: +11/-0
  • Програміст
Re: Тренінг по bash. Урок 1.
« Відповідей #16 : 2007-10-01 23:00:42 »
Попрацював трохи з бд лоу, й зрозумів, що забув одну важливу річ - останній параметр ( -- ).

Код взагалі дуже складний, розкиданий і заплутаний.
Код (( $VAR )) цілком зрозумілий для сішника але не завжди зрозумілий для bash-иста, так як код завершення (( 0 )) -> 1 , (( 1 )) -> 0. Тримати в голові що означає 0 в даному конкретному випадку трохи напрягає.
Крім того підтримка ключів --help, та -h чомусь не зроблена, хоча довідку скрипт показує.
Використання кольорів у виводі скрипта - поганий стиль. Він засиратиме вивід коли той під напр. на вхід нап. grep.
Трошки не зрозумілий стиль - з одного боку тяга до короткого коду, з іншого - if [ ... ] ; then ... fi замість [ ... ] || { ... } чи [ ... ] || ... .
Описування функції у case - дуже поганий стиль. :-)
Мені не сподобалося вирішення проблеми зі shift-ами через continue так як це обмежує можливість додавати код в тіло циклу (там повинен бути тільки shift і все). continue і break - це замасковані goto і їх не слід використовувати без особливої потреби.

Ніби все.

Чекаю коментарі на мій приклад.
[Fedora Linux]

Відсутній tech

  • Письменник
  • *****
  • дописів: 586
  • Карма: +1/-0
  • Гигик
Re: Тренінг по bash. Урок 1.
« Відповідей #17 : 2007-10-13 09:58:33 »
 В /usr/share/misc/getopts є приклади з getopts з довгими ключами. Напевне, це все-таки стандартний спосіб розбирати арґументи.

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3820
  • Карма: +11/-0
  • Програміст
Re: Тренінг по bash. Урок 1.
« Відповідей #18 : 2007-10-14 22:04:20 »
В /usr/share/misc/getopts є приклади з getopts з довгими ключами. Напевне, це все-таки стандартний спосіб розбирати арґументи.
/usr/share/doc/util-linux-2.13/getopt-parse.bash:
#!/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

Так, теж не поганий варіант. Недоліки - треба додатково вчити getopts і не забувати про те що ключі треба додавати в трьох місцях. Більше недоліків ніби нема (якщо звісно не вважати недоліком необхідність мати свіжий getopt, якого напр. нема на моєму PS2, WL500gp, і A1200 у зв'язку з його дуже великою опціональністю ;-) ).
« Змінено: 2007-10-14 22:09:45 від lvm »
[Fedora Linux]