Bash හි විධාන රේඛා තර්ක විග්‍රහ කරන්නේ කෙසේද?


1936

කියන්න, මට මෙම පේළිය සමඟ පිටපතක් තිබේ:

./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile

හෝ මෙය:

./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile 

මෙම එවැනි මාණකරනය ක්රියාත්මක වන පිළිගත් ක්රමයක් මොකක්ද එක් එක් සිද්ධිය (හෝ ඒ දෙකෙහි යම් එකතුවක් හෝ) බව $v, $fසහ $dසියලු ස්ථාපනය කරනු ලබන trueසහ $outFileසමාන වනු ඇත /fizz/someOtherFile?


1
: Zsh-පරිශීලකයන් සඳහා කළ හැකි වන zparseopts නමින් මහා builtin තියෙනවා zparseopts -D -E -M -- d=debug -debug=dඒ දෙකම ඇති -dහා --debugතුළ $debugමාලාවක් echo $+debug[1]0 හෝ 1 ආපසු අය එක් භාවිතා කරන්නේ නම්. Ref: zsh.org/mla/users/2011/msg00350.html
dezza

1
ඇත්තෙන්ම හොඳ නිබන්ධනය: linuxcommand.org/lc3_wss0120.php . මම විශේෂයෙන් "විධාන රේඛා විකල්ප" උදාහරණයට කැමතියි.
ගේබ්‍රියෙල් ස්ටැපල්ස්

Answers:


2697

ක්රමය # 1: getopt [s] නොමැතිව bash භාවිතා කිරීම

යතුරු-අගය-යුගල තර්ක සම්මත කිරීමට පොදු ක්‍රම දෙකක් නම්:

Bash Space-Separated (උදා --option argument:) (getopt [s] නොමැතිව)

භාවිතය demo-space-separated.sh -e conf -s /etc -l /usr/lib /etc/hosts

cat >/tmp/demo-space-separated.sh <<'EOF'
#!/bin/bash

POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"

case $key in
    -e|--extension)
    EXTENSION="$2"
    shift # past argument
    shift # past value
    ;;
    -s|--searchpath)
    SEARCHPATH="$2"
    shift # past argument
    shift # past value
    ;;
    -l|--lib)
    LIBPATH="$2"
    shift # past argument
    shift # past value
    ;;
    --default)
    DEFAULT=YES
    shift # past argument
    ;;
    *)    # unknown option
    POSITIONAL+=("$1") # save it in an array for later
    shift # past argument
    ;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters

echo "FILE EXTENSION  = ${EXTENSION}"
echo "SEARCH PATH     = ${SEARCHPATH}"
echo "LIBRARY PATH    = ${LIBPATH}"
echo "DEFAULT         = ${DEFAULT}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)
if [[ -n $1 ]]; then
    echo "Last line of file specified as non-opt/last argument:"
    tail -1 "$1"
fi
EOF

chmod +x /tmp/demo-space-separated.sh

/tmp/demo-space-separated.sh -e conf -s /etc -l /usr/lib /etc/hosts

ඉහත කොටස අවහිර කිරීමෙන් පිටවීම:

FILE EXTENSION  = conf
SEARCH PATH     = /etc
LIBRARY PATH    = /usr/lib
DEFAULT         =
Number files in SEARCH PATH with EXTENSION: 14
Last line of file specified as non-opt/last argument:
#93.184.216.34    example.com

Bash Equals-Separated (උදා --option=argument:) (getopt [s] නොමැතිව)

භාවිතය demo-equals-separated.sh -e=conf -s=/etc -l=/usr/lib /etc/hosts

cat >/tmp/demo-equals-separated.sh <<'EOF'
#!/bin/bash

for i in "$@"
do
case $i in
    -e=*|--extension=*)
    EXTENSION="${i#*=}"
    shift # past argument=value
    ;;
    -s=*|--searchpath=*)
    SEARCHPATH="${i#*=}"
    shift # past argument=value
    ;;
    -l=*|--lib=*)
    LIBPATH="${i#*=}"
    shift # past argument=value
    ;;
    --default)
    DEFAULT=YES
    shift # past argument with no value
    ;;
    *)
          # unknown option
    ;;
esac
done
echo "FILE EXTENSION  = ${EXTENSION}"
echo "SEARCH PATH     = ${SEARCHPATH}"
echo "LIBRARY PATH    = ${LIBPATH}"
echo "DEFAULT         = ${DEFAULT}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)
if [[ -n $1 ]]; then
    echo "Last line of file specified as non-opt/last argument:"
    tail -1 $1
fi
EOF

chmod +x /tmp/demo-equals-separated.sh

/tmp/demo-equals-separated.sh -e=conf -s=/etc -l=/usr/lib /etc/hosts

ඉහත කොටස අවහිර කිරීමෙන් පිටවීම:

FILE EXTENSION  = conf
SEARCH PATH     = /etc
LIBRARY PATH    = /usr/lib
DEFAULT         =
Number files in SEARCH PATH with EXTENSION: 14
Last line of file specified as non-opt/last argument:
#93.184.216.34    example.com

මෙම මාර්ගෝපදේශයෙහි${i#*=} "උපස්ථර ඉවත් කිරීම" සඳහා වන සෙවීම වඩා හොඳින් තේරුම් ගැනීමට . එය ක්‍රියාකාරී ලෙස අනවශ්‍ය උපප්‍රොසෙස් ලෙස හඳුන්වන හෝ අනවශ්‍ය උපප්‍රොසෙස් දෙකක් ලෙස හැඳින්වේ.`sed 's/[^=]*=//' <<< "$i"``echo "$i" | sed 's/[^=]*=//'`

ක්රමය # 2: getopt [s] සමඟ bash භාවිතා කිරීම

සිට: http://mywiki.wooledge.org/BashFAQ/035#getopts

getopt (1) සීමාවන් (පැරණි, සාපේක්ෂව මෑත getoptසංස්කරණ):

  • හිස් නූල් වන තර්ක හැසිරවිය නොහැක
  • කාවැද්දූ සුදු අවකාශය සමඟ තර්ක හැසිරවිය නොහැක

වඩාත් මෑත getoptඅනුවාද වල මෙම සීමාවන් නොමැත.

මීට අමතරව, getoptsමෙම සීමාවන් නොමැති POSIX shell (සහ වෙනත්) පිරිනැමීම . මම සරල getoptsඋදාහරණයක් ඇතුළත් කර ඇත්තෙමි .

භාවිතය demo-getopts.sh -vf /etc/hosts foo bar

cat >/tmp/demo-getopts.sh <<'EOF'
#!/bin/sh

# A POSIX variable
OPTIND=1         # Reset in case getopts has been used previously in the shell.

# Initialize our own variables:
output_file=""
verbose=0

while getopts "h?vf:" opt; do
    case "$opt" in
    h|\?)
        show_help
        exit 0
        ;;
    v)  verbose=1
        ;;
    f)  output_file=$OPTARG
        ;;
    esac
done

shift $((OPTIND-1))

[ "${1:-}" = "--" ] && shift

echo "verbose=$verbose, output_file='$output_file', Leftovers: $@"
EOF

chmod +x /tmp/demo-getopts.sh

/tmp/demo-getopts.sh -vf /etc/hosts foo bar

ඉහත කොටස අවහිර කිරීමෙන් පිටවීම:

verbose=1, output_file='/etc/hosts', Leftovers: foo bar

මෙහි ඇති වාසි getopts:

  1. එය වඩා අතේ ගෙන යා හැකි අතර වෙනත් ෂෙල් වෙඩි වැනි ක්‍රියා කරනු dashඇත.
  2. -vf filenameසාමාන්‍ය යුනික්ස් ක්‍රමයට මෙන් තනි විකල්ප කිහිපයක් ස්වයංක්‍රීයව හැසිරවිය හැක .

අවාසිය getoptsනම් එයට හැසිරවිය හැක්කේ අතිරේක කේතයකින් තොරව කෙටි විකල්ප (පමණක් -hනොවේ --help) පමණි .

සියලු වාක්‍ය ඛණ්ඩ සහ විචල්‍යයන් අදහස් කරන්නේ කුමක්ද යන්න පැහැදිලි කරන getopts නිබන්ධනයක් ඇත. Bash දී, එහි ද help getoptsතොරතුරු විය හැකි අතර,.


46
මෙය ඇත්තද? විකිපීඩියාවට අනුව නවතම GNU වැඩි දියුණු කළ අනුවාදයක් ඇති getoptඅතර එහි සියලුම ක්‍රියාකාරීත්වයන් ඇතුළත් වේ getopts. man getoptඋබුන්ටු 13.04 නිමැවුම් getopt - parse command options (enhanced)ලෙස, එබැවින් මෙම වැඩිදියුණු කළ අනුවාදය දැන් සම්මත යැයි මම සිතමි.
ලිවන්

48
ඔබේ පද්ධතියේ යම් නිශ්චිත ක්‍රමයක් යනු “සම්මත වීම” පිළිබඳ මූලික උපකල්පන සඳහා ඉතා දුර්වල පරිශ්‍රයකි.
szablica

13
Iv ලිවන්, getoptඑය ග්නූ උපයෝගීතාවයක් නොවේ, එය එහි කොටසකි util-linux.
ස්ටෙෆාන් චසෙලාස්

4
ඔබ භාවිතා කරන්නේ නම් -gt 0, ඔබගේ shiftපසු ඉවත් කරන්න, 1 න් esacවැඩි shiftකර මෙම නඩුව එක් කරන්න: *) break;;ඔබට විකල්ප නොවන තර්ක හැසිරවිය හැකිය. උදා: pastebin.com/6DJ57HTc
නිකොලස් ලැකෝම්බේ

2
ඔබ දෝංකාර දෙන්නේ නැත –default. පළමු උදාහරණයේදී, නම් මම දැනුම් –defaultපසුගිය තර්කය වේ, එය සකස් කර නැත (-ඉවත් නොවන ලෙස සැලකිය), නම් while [[ $# -gt 1 ]]ලෙස සකසා ඇත while [[ $# -gt 0 ]]
kolydart

570

කිසිදු පිළිතුරක වැඩි දියුණු කළ ගැප්ට් ගැන සඳහන් නොවේ . හා පිළිතුරු ඉහල ඡන්දය නොමඟ යවන: එය එක්කෝ නොතකා -⁠vfdස්ථානීය තර්ක පසු (මෙම විශ්රාම වැටුප් විසින් ඉල්ලා) ශෛලිය කෙටි විකල්ප හෝ විකල්ප (ද විශ්රාම වැටුප් විසින් ඉල්ලා); එය විග්‍රහ කිරීමේ දෝෂ නොසලකා හරියි. වෙනුවට:

  • getoptUtil-linux හෝ කලින් GNU glibc වෙතින් වැඩි දියුණු කරන ලද භාවිතය . 1
  • එය getopt_long()GNU glibc හි C ශ්‍රිතය සමඟ ක්‍රියා කරයි .
  • ඇත සියලුම ප්රයෝජනවත් වැදගත් ලක්ෂනයක් (අනෙක් ඒවා ඇති කරන්නේ නැහැ):
    • අවකාශ 2, අක්ෂර උපුටා දැක්වීම සහ තර්ක 2 හි ද්විමය පවා හසුරුවයි (වැඩි දියුණු getoptනොකළ අයට මෙය කළ නොහැක)
    • එයට අවසානයේ විකල්ප හැසිරවිය හැකිය: script.sh -o outFile file1 file2 -v(මෙය getoptsනොකරයි)
    • ඉඩ- =ශෛලීය දිගු විකල්ප: script.sh --outfile=fileOut --infile fileIn(ස්වයං විග්‍රහ කිරීම සඳහා දෙකටම ඉඩ දීම දිගු වේ)
    • ඒකාබද්ධ කෙටි විකල්ප වලට ඉඩ දෙයි, උදා. -vfd(ස්වයං විග්‍රහ කිරීම නම් සැබෑ වැඩ)
    • උදා: වෛද්ය තුමනි විකල්පය-තර්ක ඉඩ -oOutfileහෝ-vfdoOutfile
  • මේ වන විටත් 3 ක් පැරණි බැවින් GNU පද්ධතියක් මෙය අස්ථානගත වී ඇත (උදා: ඕනෑම ලිනක්ස් සතුව එය තිබේ).
  • ඔබට එහි පැවැත්ම පරීක්ෂා කළ හැකිය: getopt --test→ ප්‍රතිලාභ අගය 4.
  • වෙනත් getoptහෝ ෂෙල්-බිල්ඩින් getoptsසීමිත භාවිතයක් ඇත.

පහත ඇමතුම්

myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
myscript -v -f -d -o/fizz/someOtherFile -- ./foo/bar/someFile
myscript --verbose --force --debug ./foo/bar/someFile -o/fizz/someOtherFile
myscript --output=/fizz/someOtherFile ./foo/bar/someFile -vfd
myscript ./foo/bar/someFile -df -v --output /fizz/someOtherFile

සියල්ල ආපසු

verbose: y, force: y, debug: y, in: ./foo/bar/someFile, out: /fizz/someOtherFile

පහත සඳහන් දෑ සමඟ myscript

#!/bin/bash
# saner programming env: these switches turn some bugs into errors
set -o errexit -o pipefail -o noclobber -o nounset

# -allow a command to fail with !’s side effect on errexit
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
! getopt --test > /dev/null 
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
    echo 'I’m sorry, `getopt --test` failed in this environment.'
    exit 1
fi

OPTIONS=dfo:v
LONGOPTS=debug,force,output:,verbose

# -regarding ! and PIPESTATUS see above
# -temporarily store output to be able to check for errors
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
# -pass arguments only via   -- "$@"   to separate them correctly
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
    # e.g. return value is 1
    #  then getopt has complained about wrong arguments to stdout
    exit 2
fi
# read getopt’s output this way to handle the quoting right:
eval set -- "$PARSED"

d=n f=n v=n outFile=-
# now enjoy the options in order and nicely split until we see --
while true; do
    case "$1" in
        -d|--debug)
            d=y
            shift
            ;;
        -f|--force)
            f=y
            shift
            ;;
        -v|--verbose)
            v=y
            shift
            ;;
        -o|--output)
            outFile="$2"
            shift 2
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "Programming error"
            exit 3
            ;;
    esac
done

# handle non-option arguments
if [[ $# -ne 1 ]]; then
    echo "$0: A single input file is required."
    exit 4
fi

echo "verbose: $v, force: $f, debug: $d, in: $1, out: $outFile"

1 වැඩි දියුණු getopt Cygwin ඇතුළු වඩාත් ම "bash-පද්ධති", ලබා ගත හැකිය; OS X හි බීර ස්ථාපනය කිරීමට උත්සාහ කරන්න gnu-getopt හෝsudo port install getopt
2 POSIXexec()සම්මුතීන්ට ද්විමය NULL විධාන රේඛා තර්ක තුළ සම්මත කිරීමට විශ්වාසදායක ක්‍රමයක් නොමැත; එම බයිට්1997 දී හෝ ඊට පෙර නිකුත් කළ
3 වන පළමු අනුවාදයඅකාලයේ අවසන් කරයි(මම එය නිරීක්ෂණය කළේ 1997 දක්වා පමණි)


4
මේ සඳහා ස්තූතියි. යන්තම් විශේෂාංගය මේසයෙන් තහවුරු en.wikipedia.org/wiki/Getopts ඔබ දිගු විකල්ප සඳහා සහාය අවශ්ය නම්, ඔබ Solaris මත නෑ, getoptයන්න මාර්ගය වන්නේ.
johncip

4
මා විශ්වාස කරන එකම අවවාදය getoptනම්, එය රැප් ස්ක්‍රිප්ට් සඳහා පහසු ලෙස භාවිතා කළ නොහැකි වන අතර, යමෙකුට එතීමේ ස්ක්‍රිප්ටයට විශේෂිත විකල්ප කිහිපයක් තිබිය හැකි අතර, එතුම-ස්ක්‍රිප්ට් නොවන විකල්පයන් ඔතා ක්‍රියාත්මක කළ හැකි, නොවෙනස්ව තබන්න. මම කියමු, මට grepඑතුම එතී ඇති mygrepඅතර මට --fooවිශේෂිත විකල්පයක් ඇත mygrep, එවිට මට කළ නොහැකි mygrep --foo -A 2අතර -A 2ස්වයංක්‍රීයව සම්මත වී ඇත grep; මම අවශ්ය කරන්නේ mygrep --foo -- -A 2. මෙන්න ඔබේ විසඳුම මත මගේ ක්‍රියාත්මක කිරීම .
කෞෂාල් මෝඩි

2
obbobpaul util-linux පිළිබඳ ඔබේ ප්‍රකාශය වැරදි සහ නොමඟ යවන සුළු ය: පැකේජය උබුන්ටු / ඩේබියන් හි “අත්‍යවශ්‍ය” ලෙස සලකුණු කර ඇත. එනිසා එය සෑම විටම ස්ථාපනය කර ඇත. - ඔබ කතා කරන්නේ කුමන ඩිස්ට්‍රෝස් ගැනද (එය ඔබ කියන්නේ එය අරමුණක් මත ස්ථාපනය කළ යුතු බවයි)?
රොබට් සීමර්

3
අවම වශයෙන් වර්තමාන 10.14.3 දක්වා මෙය මැක් මත ක්‍රියා නොකරන බව සලකන්න. නැව්ගත කිරීම 1999 සිට BSD getopt වේ ...
jjj

2
ප්‍රතිලාභ අගය බූලියන් ප්‍රතික්ෂේප කිරීම. එහි අතුරු effect ලය: විධානයක් අසමත් වීමට ඉඩ දෙන්න (එසේ නොමැතිනම් errexit මඟින් වැඩසටහන වැරදීමකින් නවතා දමනු ඇත). - පිටපතෙහි අදහස් ඔබට තවත් කියයි. එසේ නොමැති නම්:man bash
රොබට් සීමර්

159

වඩාත් සංක්ෂිප්ත මාර්ගය

script.sh

#!/bin/bash

while [[ "$#" -gt 0 ]]; do
    case $1 in
        -d|--deploy) deploy="$2"; shift ;;
        -u|--uglify) uglify=1 ;;
        *) echo "Unknown parameter passed: $1"; exit 1 ;;
    esac
    shift
done

echo "Should deploy? $deploy"
echo "Should uglify? $uglify"

භාවිතය:

./script.sh -d dev -u

# OR:

./script.sh --deploy dev --uglify

3
මම කරන්නේ මෙයයි. while [[ "$#" > 1 ]]රේඛාව බූලියන් ධජයකින් අවසන් කිරීමට මට සහාය වීමට අවශ්‍ය නම් කළ යුතුය ./script.sh --debug dev --uglify fast --verbose. උදාහරණය: gist.github.com/hfossli/4368aa5a577742c3c9f9266ed214aa58
hfossli

13
වාව්! සරල හා පිරිසිදුයි! මම මෙය භාවිතා කරන්නේ එලෙසයි
hfossli

2
මූලාශ්‍රය සමඟ ගනුදෙනු කිරීමට හෝ ඔබේ ක්‍රියාකාරිත්වය සැබවින්ම ආරම්භ වන්නේ කොතැනින්දැයි මිනිසුන් කල්පනා කරනවාට වඩා එක් එක් ස්ක්‍රිප්ටයට ඇලවීම සඳහා මෙය වඩාත් සුදුසුය.
රියල්හැන්ඩි

අවවාදයයි: මෙය අනුපිටපත් තර්ක ඉවසා සිටියි, නවතම තර්කය පවතී. උදා: ./script.sh -d dev -d prodප්රතිපලය වනු deploy == 'prod'. මම එය කෙසේ හෝ භාවිතා කළෙමි: P :): +1:
yair

මම මෙය භාවිතා කරමි (ස්තූතියි!) නමුත් එය හිස් තර්ක අගයට ඉඩ දෙන බව සලකන්න, උදා: ./script.sh -dදෝෂයක් ජනනය නොකර $deployහිස් නූලකට සකසන්න .
EM0

137

සිට: සුළු වෙනස් කිරීම් සහිත Digitalpeer.com

භාවිතය myscript.sh -p=my_prefix -s=dirname -l=libname

#!/bin/bash
for i in "$@"
do
case $i in
    -p=*|--prefix=*)
    PREFIX="${i#*=}"

    ;;
    -s=*|--searchpath=*)
    SEARCHPATH="${i#*=}"
    ;;
    -l=*|--lib=*)
    DIR="${i#*=}"
    ;;
    --default)
    DEFAULT=YES
    ;;
    *)
            # unknown option
    ;;
esac
done
echo PREFIX = ${PREFIX}
echo SEARCH PATH = ${SEARCHPATH}
echo DIRS = ${DIR}
echo DEFAULT = ${DEFAULT}

මෙම මාර්ගෝපදේශයෙහි${i#*=} "උපස්ථර ඉවත් කිරීම" සඳහා වන සෙවීම වඩා හොඳින් තේරුම් ගැනීමට . එය ක්‍රියාකාරී ලෙස අනවශ්‍ය උපප්‍රොසෙස් ලෙස හඳුන්වන හෝ අනවශ්‍ය උපප්‍රොසෙස් දෙකක් ලෙස හැඳින්වේ.`sed 's/[^=]*=//' <<< "$i"``echo "$i" | sed 's/[^=]*=//'`


4
පිළිවෙළකට! අවකාශය වෙන් කළ තර්ක සඳහා මෙය ක්‍රියා නොකරනු ඇත à la mount -t tempfs .... එක් සමහරවිට වගේ දෙයක් හරහා මෙම අදාල කරගන්නේ while [ $# -ge 1 ]; do param=$1; shift; case $param in; -p) prefix=$1; shift;;ආදිය
තෝබියස් Kienzler

3
මෙය -vfdශෛලිය ඒකාබද්ධ කෙටි විකල්ප හැසිරවිය නොහැක .
රොබට් සීමර්

106

getopt()/ getopts()හොඳ විකල්පයක්. මෙතැන් සිට සොරකම් කර ඇත :

"Getopt" හි සරල භාවිතය මෙම කුඩා පිටපතෙහි දැක්වේ:

#!/bin/bash
echo "Before getopt"
for i
do
  echo $i
done
args=`getopt abc:d $*`
set -- $args
echo "After getopt"
for i
do
  echo "-->$i"
done

අප පවසා ඇති දෙය නම් -a, -b, -c හෝ -d ඕනෑම දෙයකට ඉඩ දෙනු ඇත, නමුත් එම -c පසුව තර්කයක් අනුගමනය කරයි ("c:" එය පවසයි).

අපි මෙය "g" ලෙස අමතා එය උත්සාහ කර බැලුවහොත්:

bash-2.05a$ ./g -abc foo
Before getopt
-abc
foo
After getopt
-->-a
-->-b
-->-c
-->foo
-->--

අපි තර්ක දෙකකින් ආරම්භ කරන අතර, "getopt" විකල්පයන් බිඳ දමා සෑම එකක්ම තමන්ගේම තර්කයට දමයි. එය "-" ද එකතු කළේය.


4
භාවිතා කිරීම $*යනු බිඳුණු භාවිතයයි getopt. (එය අවකාශයන් සමඟ තර්ක විතර්ක කරයි.) නිසි භාවිතය සඳහා මගේ පිළිතුර බලන්න .
රොබට් සීමර්

එය වඩාත් සංකීර්ණ කිරීමට ඔබට අවශ්‍ය ඇයි?
SDsolar

Att මාට් ජේ, ස්ක්‍රිප්ටයේ පළමු කොටස (i සඳහා) ඔබ $ i වෙනුවට "$ i" භාවිතා කරන්නේ නම් ඒවායේ ඇති අවකාශයන් සමඟ තර්ක හැසිරවිය හැකිය. Getopts හට අවකාශයන් සමඟ තර්ක හැසිරවිය හැකි බවක් නොපෙනේ. I for loop සඳහා getopt භාවිතා කිරීමේ වාසිය කුමක්ද?
thebunnyrules

101

නොසලකා හැරීමට තවත් උදාහරණයක් එකතු කිරීමේ අවදානමක, මෙන්න මගේ යෝජනා ක්‍රමය.

  • හසුරුවයි -n argසහ--name=arg
  • අවසානයේ තර්ක වලට ඉඩ දෙයි
  • කිසිවක් වැරදියට ලියා ඇත්නම් නිවැරදි දෝෂ පෙන්වයි
  • අනුකූලයි, bashisms භාවිතා නොකරයි
  • කියවිය හැකි, පුඩුවක් තුළ තත්වය පවත්වා ගැනීම අවශ්‍ය නොවේ

එය යමෙකුට ප්‍රයෝජනවත් යැයි සිතමි.

while [ "$#" -gt 0 ]; do
  case "$1" in
    -n) name="$2"; shift 2;;
    -p) pidfile="$2"; shift 2;;
    -l) logfile="$2"; shift 2;;

    --name=*) name="${1#*=}"; shift 1;;
    --pidfile=*) pidfile="${1#*=}"; shift 1;;
    --logfile=*) logfile="${1#*=}"; shift 1;;
    --name|--pidfile|--logfile) echo "$1 requires an argument" >&2; exit 1;;

    -*) echo "unknown option: $1" >&2; exit 1;;
    *) handle_argument "$1"; shift 1;;
  esac
done

4
ප්රමාදය පිළිබඳ කනගාටුයි. මගේ ස්ක්‍රිප්ටයේ, handle_argument ශ්‍රිතයට සියලු විකල්ප නොවන තර්ක ලැබේ. ඔබට එම රේඛාව ඔබ කැමති ඕනෑම දෙයක් සමඟ ප්‍රතිස්ථාපනය කළ හැකිය, සමහර විට *) die "unrecognized argument: $1"හෝ විචල්‍යයන් වෙත ආග්ස් එකතු කරන්න *) args+="$1"; shift 1;;.
බ්‍රොන්සන්

අරුම පුදුම! මම පිළිතුරු කිහිපයක් අත්හදා බැලුවෙමි, නමුත් බොහෝ ස්ථානීය පරාමිතීන් (කොඩි වලට පෙර සහ පසු) ඇතුළුව සියලු අවස්ථාවන් සඳහා ක්‍රියා කළ එකම එක මෙයයි
ගිල්හර්ම් ගාර්නියර්

2
හොඳ සංක්ෂිප්ත කේතයක්, නමුත් -n භාවිතා කිරීම සහ වෙනත් කිසිදු ආරුක්කු දෝෂයක් හේතුවෙන් අසීමිත ලූපයක් ඇති කරයි shift 2, shiftඒ වෙනුවට දෙවරක් නිකුත් කරයි shift 2. සංස්කරණය යෝජනා කළේය.
lauksas

කේතය සරල හා කුඩා ලෙස තබා ගනිමින් ප්‍රයෝජනවත් අංග කිහිපයක් එක් කිරීමට මම සංස්කරණයක් කර ඇත (එය සමාලෝචනය සඳහා බලා සිටී). වඩා සුන්දර විශේෂාංග සඳහා, තනි තර්කය තුළ බහු එක් ලිපියක් විකල්ප වැනි, ඔබ උත්සාහ කළ යුතුයි getoptහෝ getopts.
leogama

42

මම මෙම ප්‍රශ්නයට අවුරුදු 4 ක් පමණ ප්‍රමාදයි, නමුත් ආපසු ලබා දීමට අවශ්‍යයි. මගේ පැරණි ඇඩොක් පරාම් විග්‍රහ කිරීම සඳහා මම කලින් පිළිතුරු ආරම්භක ලක්ෂ්‍යයක් ලෙස භාවිතා කළෙමි. මම පහත දැක්වෙන අච්චු කේතය නැවත සකස් කළෙමි. එය දිගු හෝ කෙටි පරාමිතීන් හසුරුවයි, = හෝ අවකාශයෙන් වෙන් කරන ලද තර්ක භාවිතා කරයි, මෙන්ම කෙටි කෙටි පරාමිතීන් සමූහගත කර ඇත. අවසාන වශයෙන් එය පරාමිතික නොවන ඕනෑම තර්කයක් $ 1, $ 2 .. විචල්‍යයන් වෙත නැවත ඇතුල් කරයි. එය ප්‍රයෝජනවත් යැයි මම සිතමි.

#!/usr/bin/env bash

# NOTICE: Uncomment if your script depends on bashisms.
#if [ -z "$BASH_VERSION" ]; then bash $0 $@ ; exit $? ; fi

echo "Before"
for i ; do echo - $i ; done


# Code template for parsing command line parameters using only portable shell
# code, while handling both long and short params, handling '-f file' and
# '-f=file' style param data and also capturing non-parameters to be inserted
# back into the shell positional parameters.

while [ -n "$1" ]; do
        # Copy so we can modify it (can't modify $1)
        OPT="$1"
        # Detect argument termination
        if [ x"$OPT" = x"--" ]; then
                shift
                for OPT ; do
                        REMAINS="$REMAINS \"$OPT\""
                done
                break
        fi
        # Parse current opt
        while [ x"$OPT" != x"-" ] ; do
                case "$OPT" in
                        # Handle --flag=value opts like this
                        -c=* | --config=* )
                                CONFIGFILE="${OPT#*=}"
                                shift
                                ;;
                        # and --flag value opts like this
                        -c* | --config )
                                CONFIGFILE="$2"
                                shift
                                ;;
                        -f* | --force )
                                FORCE=true
                                ;;
                        -r* | --retry )
                                RETRY=true
                                ;;
                        # Anything unknown is recorded for later
                        * )
                                REMAINS="$REMAINS \"$OPT\""
                                break
                                ;;
                esac
                # Check for multiple short options
                # NOTICE: be sure to update this pattern to match valid options
                NEXTOPT="${OPT#-[cfr]}" # try removing single short opt
                if [ x"$OPT" != x"$NEXTOPT" ] ; then
                        OPT="-$NEXTOPT"  # multiple short opts, keep going
                else
                        break  # long form, exit inner loop
                fi
        done
        # Done with that param. move to next
        shift
done
# Set the non-parameters back into the positional parameters ($1 $2 ..)
eval set -- $REMAINS


echo -e "After: \n configfile='$CONFIGFILE' \n force='$FORCE' \n retry='$RETRY' \n remains='$REMAINS'"
for i ; do echo - $i ; done

මෙම කේතයට මෙවැනි තර්ක සමඟ විකල්ප හැසිරවිය නොහැක : -c1. =ඔවුන්ගේ තර්ක වලින් කෙටි විකල්ප වෙන් කිරීම භාවිතා කිරීම අසාමාන්‍යය ...
රොබට් සීමර්

2
මෙම ප්‍රයෝජනවත් කේත කැබැල්ල සමඟ මම ගැටලු දෙකකට මුහුණ දුන්නෙමි: 1) "-c = foo" හි "මාරුව" ඊළඟ පරාමිතිය අනුභව කිරීම අවසන් කරයි; සහ 2) ඒකාබද්ධ කළ හැකි කෙටි විකල්ප සඳහා '[cfr] "රටාවට' c 'ඇතුළත් නොකළ යුතුය.
sfnd

36

ස්ක්‍රිප්ට් වල අතේ ගෙන යා හැකි විග්‍රහ කිරීම ලිවීමේ කාරණය මා සොයාගෙන ඇති අතර, ඔබේ ස්ක්‍රිප්ට් සඳහා තර්ක විග්‍රහ කිරීමේ කේතය ජනනය කළ හැකි ෆොස් කේත උත්පාදක යන්ත්‍රයක් වන ආර්ග්බාෂ් ලියා ඇති අතර එයට හොඳ ලක්ෂණ කිහිපයක් ඇත:

https://argbash.io


ආර්ග්බෑෂ් ලිවීමට ස්තූතියි, මම එය භාවිතා කළ අතර එය හොඳින් ක්‍රියාත්මක වන බව මට පෙනී ගියේය. මම වැඩිපුරම ආග්බැෂ් සඳහා ගියේ එය OS X 10.11 El Capitan හි ඇති පැරණි bash 3.x සඳහා සහය දක්වන කේත උත්පාදකයක් වන බැවිනි. එකම අවාසිය නම් මොඩියුලයක් ඇමතීමට සාපේක්ෂව කේත උත්පාදක ප්‍රවේශය යනු ඔබේ ප්‍රධාන ස්ක්‍රිප්ටයේ කේත විශාල ප්‍රමාණයක් තිබීමයි.
රිච්වෙල්

ඔබේ ස්ක්‍රිප්ටයට ඇතුළත් කළ හැකි හෝ ඔබට එය වෙනම ගොනුවක තබා එය මූලාශ්‍රයක් ලබා ගත හැකි වන පරිදි ඔබට ආග්බාෂ් භාවිතා කළ හැකිය. එය නිරූපණය කිරීම සඳහා මම උදාහරණයක් එකතු කර ඇති අතර, ලේඛනයේ ද එය වඩාත් පැහැදිලි කර ඇත්තෙමි.
බුබ්ලා

දැන ගැනීමට ලැබීම සතුටක්. එම උදාහරණය සිත්ගන්නාසුළු නමුත් තවමත් පැහැදිලි නැත - සමහර විට ඔබට ජනනය කරන ලද ස්ක්‍රිප්ටයේ නම 'parse_lib.sh' හෝ ඊට සමාන ලෙස වෙනස් කර ප්‍රධාන ස්ක්‍රිප්ට් එය හඳුන්වන ස්ථානය පෙන්විය හැකිය (එතීෙම් ස්ක්‍රිප්ට් කොටසේ මෙන් එය වඩාත් සංකීර්ණ භාවිත අවස්ථාවකි).
රිච්වෙල්

ප්රශ්න argbash මෑත අනුවාදය ආමන්ත්රණය කරන ලදී: Documentation, වැඩි දියුණු කර ඇත වූ quickstart argbash-init තිර රචනය හඳුන්වා දී ඇති අතර, ඔබ පවා අන්තර්ජාලය ඔස්සේ argbash භාවිතා කළ හැකිය argbash.io/generate
bubla

29

මගේ පිළිතුර බොහෝ දුරට පදනම් වී ඇත්තේ බ un නෝ බ්‍රොනොස්කිගේ පිළිතුර මත , නමුත් මම ඔහුගේ පිරිසිදු බාෂ් ක්‍රියාත්මක කිරීම් දෙක මා නිතර නිතර භාවිතා කරන එකක් බවට පත් කළෙමි.

# As long as there is at least one more argument, keep looping
while [[ $# -gt 0 ]]; do
    key="$1"
    case "$key" in
        # This is a flag type option. Will catch either -f or --foo
        -f|--foo)
        FOO=1
        ;;
        # Also a flag type option. Will catch either -b or --bar
        -b|--bar)
        BAR=1
        ;;
        # This is an arg value type option. Will catch -o value or --output-file value
        -o|--output-file)
        shift # past the key and to the value
        OUTPUTFILE="$1"
        ;;
        # This is an arg=value type option. Will catch -o=value or --output-file=value
        -o=*|--output-file=*)
        # No need to shift here since the value is part of the same string
        OUTPUTFILE="${key#*=}"
        ;;
        *)
        # Do whatever you want with extra options
        echo "Unknown option '$key'"
        ;;
    esac
    # Shift after checking all the cases to get the next option
    shift
done

මෙය ඔබට අවකාශය වෙන් කළ විකල්ප / අගයන් මෙන්ම සමාන අර්ථ දක්වා ඇති අගයන් ලබා ගැනීමට ඉඩ සලසයි.

එබැවින් ඔබට මෙය භාවිතයෙන් ඔබේ ස්ක්‍රිප්ට් ධාවනය කළ හැකිය:

./myscript --foo -b -o /fizz/file.txt

මෙන්ම:

./myscript -f --bar -o=/fizz/file.txt

දෙකම එකම අවසාන ප්‍රති .ලයක් තිබිය යුතුය.

PROS:

  • -ARg = අගය සහ -arg අගය යන දෙකම සඳහා ඉඩ ලබා දේ

  • ඔබට බාෂ් හි භාවිතා කළ හැකි ඕනෑම ආගන් නාමයක් සමඟ ක්‍රියා කරයි

    • තේරුම -a හෝ -arg හෝ --arg හෝ -arg හෝ ඕනෑම දෙයක්
  • පිරිසිදු බාෂ්. Getopt හෝ getopts ඉගෙන ගැනීමට / භාවිතා කිරීමට අවශ්‍ය නැත

CONS:

  • ආග්ස් ඒකාබද්ධ කළ නොහැක

    • තේරුම නැත -abc. ඔබ කළ යුත්තේ -a -b -c

මගේ හිස මුදුනේ සිට මට සිතිය හැකි එකම වාසි / අවාසි මේවායි


17

@ ගුනීසස්ගේ විශිෂ් answer පිළිතුර විස්තාරණය කරමින්, පරිශීලකයාට ඔවුන් කැමති ඕනෑම වාක්‍ය ඛණ්ඩයක් භාවිතා කිරීමට ඉඩ සලසන නවීකරණයකි, උදා.

command -x=myfilename.ext --another_switch 

එදිරිව

command -x myfilename.ext --another_switch

එනම් සමානාත්මතාවය සුදු අවකාශයෙන් ප්‍රතිස්ථාපනය කළ හැකි බවයි.

මෙම "නොපැහැදිලි අර්ථ නිරූපණය" ඔබේ රුචිකත්වයට නොගැලපේ, නමුත් ඔබ වෙනත් උපයෝගීතා සමඟ හුවමාරු කළ හැකි ස්ක්‍රිප්ට් සාදන්නේ නම් (මගේ මෙන්ම ffmpeg සමඟ ක්‍රියා කළ යුතුය) නම්යශීලීභාවය ප්‍රයෝජනවත් වේ.

STD_IN=0

prefix=""
key=""
value=""
for keyValue in "$@"
do
  case "${prefix}${keyValue}" in
    -i=*|--input_filename=*)  key="-i";     value="${keyValue#*=}";; 
    -ss=*|--seek_from=*)      key="-ss";    value="${keyValue#*=}";;
    -t=*|--play_seconds=*)    key="-t";     value="${keyValue#*=}";;
    -|--stdin)                key="-";      value=1;;
    *)                                      value=$keyValue;;
  esac
  case $key in
    -i) MOVIE=$(resolveMovie "${value}");  prefix=""; key="";;
    -ss) SEEK_FROM="${value}";          prefix=""; key="";;
    -t)  PLAY_SECONDS="${value}";           prefix=""; key="";;
    -)   STD_IN=${value};                   prefix=""; key="";; 
    *)   prefix="${keyValue}=";;
  esac
done

15

මම හිතන්නේ මෙය භාවිතා කිරීමට තරම් සරල ය:

#!/bin/bash
#

readopt='getopts $opts opt;rc=$?;[ $rc$opt == 0? ]&&exit 1;[ $rc == 0 ]||{ shift $[OPTIND-1];false; }'

opts=vfdo:

# Enumerating options
while eval $readopt
do
    echo OPT:$opt ${OPTARG+OPTARG:$OPTARG}
done

# Enumerating arguments
for arg
do
    echo ARG:$arg
done

ආයාචනා උදාහරණය:

./myscript -v -do /fizz/someOtherFile -f ./foo/bar/someFile
OPT:v 
OPT:d 
OPT:o OPTARG:/fizz/someOtherFile
OPT:f 
ARG:./foo/bar/someFile

1
මම සියල්ල කියවූ අතර මෙය මගේ ප්‍රියතම එකයි. මම -a=1ආර්ක් ශෛලිය ලෙස භාවිතා කිරීමට කැමති නැත . ප්‍රධාන විකල්පය වන විකල්පයන් සහ පසුව තනි පරතරයක් ඇති විශේෂ විකල්පයන් තැබීමට මම කැමැත්තෙමි -o option. මම argvs කියවීමට සරලම-එදිරිව-වඩා හොඳ ක්‍රමයක් සොයමි.
m3nda

එය ඉතා හොඳින් ක්‍රියාත්මක වන නමුත් ඔබ තර්කයක් නොවන අය වෙත යොමු කළහොත්: විකල්පය පහත සඳහන් සියලු විකල්පයන් තර්ක ලෙස ගනු ලැබේ. ඔබට ./myscript -v -d fail -o /fizz/someOtherFile -f ./foo/bar/someFileඔබේම පිටපතක් සමඟ මෙම රේඛාව පරීක්ෂා කළ හැකිය . -d විකල්පය d ලෙස සකසා නැත:
m3nda

13

මේ උදාහරණය අපට පෙන්වනවා භාවිතා කරන ආකාරය getoptසහ evalසහ HEREDOCසහ shiftසහ පහත සඳහන් බව අවශ්ය අගය තොරව කෙටි හා දිගු පරාමිතීන් හැසිරවීමට. එසේම ස්විච් / කේස් ප්‍රකාශය සංක්ෂිප්ත හා අනුගමනය කිරීමට පහසුය.

#!/usr/bin/env bash

# usage function
function usage()
{
   cat << HEREDOC

   Usage: $progname [--num NUM] [--time TIME_STR] [--verbose] [--dry-run]

   optional arguments:
     -h, --help           show this help message and exit
     -n, --num NUM        pass in a number
     -t, --time TIME_STR  pass in a time string
     -v, --verbose        increase the verbosity of the bash script
     --dry-run            do a dry run, dont change any files

HEREDOC
}  

# initialize variables
progname=$(basename $0)
verbose=0
dryrun=0
num_str=
time_str=

# use getopt and store the output into $OPTS
# note the use of -o for the short options, --long for the long name options
# and a : for any option that takes a parameter
OPTS=$(getopt -o "hn:t:v" --long "help,num:,time:,verbose,dry-run" -n "$progname" -- "$@")
if [ $? != 0 ] ; then echo "Error in command line arguments." >&2 ; usage; exit 1 ; fi
eval set -- "$OPTS"

while true; do
  # uncomment the next line to see how shift is working
  # echo "\$1:\"$1\" \$2:\"$2\""
  case "$1" in
    -h | --help ) usage; exit; ;;
    -n | --num ) num_str="$2"; shift 2 ;;
    -t | --time ) time_str="$2"; shift 2 ;;
    --dry-run ) dryrun=1; shift ;;
    -v | --verbose ) verbose=$((verbose + 1)); shift ;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

if (( $verbose > 0 )); then

   # print out all the parameters we read in
   cat <<-EOM
   num=$num_str
   time=$time_str
   verbose=$verbose
   dryrun=$dryrun
EOM
fi

# The rest of your script below

ඉහත පිටපතෙහි වඩාත්ම වැදගත් රේඛා මේවා ය:

OPTS=$(getopt -o "hn:t:v" --long "help,num:,time:,verbose,dry-run" -n "$progname" -- "$@")
if [ $? != 0 ] ; then echo "Error in command line arguments." >&2 ; exit 1 ; fi
eval set -- "$OPTS"

while true; do
  case "$1" in
    -h | --help ) usage; exit; ;;
    -n | --num ) num_str="$2"; shift 2 ;;
    -t | --time ) time_str="$2"; shift 2 ;;
    --dry-run ) dryrun=1; shift ;;
    -v | --verbose ) verbose=$((verbose + 1)); shift ;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

කෙටියෙන්, කාරණයට, කියවිය හැකි සහ සෑම දෙයක්ම හසුරුවයි (IMHO).

යමෙකුට උපකාර කරන බලාපොරොත්තුව.


1
මෙය හොඳම පිළිතුරු වලින් එකකි.
පොලිවර්ල් මහතා

11

parse_paramsවිධාන රේඛාවෙන් පරාමිතීන් විග්‍රහ කරන ශ්‍රිතය මම ඔබට ලබා දෙමි .

  1. එය පිරිසිදු බාෂ් විසඳුමක්, අමතර උපයෝගිතා නොමැත.
  2. ගෝලීය විෂය පථය දූෂණය නොකරයි.
  3. ඔබට තව දුරටත් තර්කනය ගොඩනගා ගත හැකි විචල්යයන් භාවිතා කිරීම සඳහා සරලව ඔබට ආපසු ලබා දේ.
  4. පරාමිතීන්ට පෙර ඉරෙහි ප්‍රමාණය වැදගත් නොවේ ( --allසමාන -allවේ all=all)

පහත පිටපත පිටපත්-පේස්ට් වැඩ කිරීමේ නිරූපණයකි. show_useභාවිතා කරන්නේ කෙසේද යන්න තේරුම් ගැනීමට ශ්‍රිතය බලන්නparse_params .

සීමාවන්:

  1. අවකාශයෙන් වෙන් කරන ලද පරාමිතීන් සඳහා සහය නොදක්වයි (-d 1 )
  2. Param නම් එසේ ඉතුරු අහිමි වනු ඇත --any-paramහා-anyparam සමාන වේ
  3. eval $(parse_params "$@")bash ශ්‍රිතය තුළ භාවිතා කළ යුතුය (එය ගෝලීය විෂය පථය තුළ ක්‍රියා නොකරනු ඇත)

#!/bin/bash

# Universal Bash parameter parsing
# Parse equal sign separated params into named local variables
# Standalone named parameter value will equal its param name (--force creates variable $force=="force")
# Parses multi-valued named params into an array (--path=path1 --path=path2 creates ${path[*]} array)
# Puts un-named params as-is into ${ARGV[*]} array
# Additionally puts all named params as-is into ${ARGN[*]} array
# Additionally puts all standalone "option" params as-is into ${ARGO[*]} array
# @author Oleksii Chekulaiev
# @version v1.4.1 (Jul-27-2018)
parse_params ()
{
    local existing_named
    local ARGV=() # un-named params
    local ARGN=() # named params
    local ARGO=() # options (--params)
    echo "local ARGV=(); local ARGN=(); local ARGO=();"
    while [[ "$1" != "" ]]; do
        # Escape asterisk to prevent bash asterisk expansion, and quotes to prevent string breakage
        _escaped=${1/\*/\'\"*\"\'}
        _escaped=${_escaped//\'/\\\'}
        _escaped=${_escaped//\"/\\\"}
        # If equals delimited named parameter
        nonspace="[^[:space:]]"
        if [[ "$1" =~ ^${nonspace}${nonspace}*=..* ]]; then
            # Add to named parameters array
            echo "ARGN+=('$_escaped');"
            # key is part before first =
            local _key=$(echo "$1" | cut -d = -f 1)
            # Just add as non-named when key is empty or contains space
            if [[ "$_key" == "" || "$_key" =~ " " ]]; then
                echo "ARGV+=('$_escaped');"
                shift
                continue
            fi
            # val is everything after key and = (protect from param==value error)
            local _val="${1/$_key=}"
            # remove dashes from key name
            _key=${_key//\-}
            # skip when key is empty
            # search for existing parameter name
            if (echo "$existing_named" | grep "\b$_key\b" >/dev/null); then
                # if name already exists then it's a multi-value named parameter
                # re-declare it as an array if needed
                if ! (declare -p _key 2> /dev/null | grep -q 'declare \-a'); then
                    echo "$_key=(\"\$$_key\");"
                fi
                # append new value
                echo "$_key+=('$_val');"
            else
                # single-value named parameter
                echo "local $_key='$_val';"
                existing_named=" $_key"
            fi
        # If standalone named parameter
        elif [[ "$1" =~ ^\-${nonspace}+ ]]; then
            # remove dashes
            local _key=${1//\-}
            # Just add as non-named when key is empty or contains space
            if [[ "$_key" == "" || "$_key" =~ " " ]]; then
                echo "ARGV+=('$_escaped');"
                shift
                continue
            fi
            # Add to options array
            echo "ARGO+=('$_escaped');"
            echo "local $_key=\"$_key\";"
        # non-named parameter
        else
            # Escape asterisk to prevent bash asterisk expansion
            _escaped=${1/\*/\'\"*\"\'}
            echo "ARGV+=('$_escaped');"
        fi
        shift
    done
}

#--------------------------- DEMO OF THE USAGE -------------------------------

show_use ()
{
    eval $(parse_params "$@")
    # --
    echo "${ARGV[0]}" # print first unnamed param
    echo "${ARGV[1]}" # print second unnamed param
    echo "${ARGN[0]}" # print first named param
    echo "${ARG0[0]}" # print first option param (--force)
    echo "$anyparam"  # print --anyparam value
    echo "$k"         # print k=5 value
    echo "${multivalue[0]}" # print first value of multi-value
    echo "${multivalue[1]}" # print second value of multi-value
    [[ "$force" == "force" ]] && echo "\$force is set so let the force be with you"
}

show_use "param 1" --anyparam="my value" param2 k=5 --force --multi-value=test1 --multi-value=test2

ඔබගේ බාෂ් ස්ක්‍රිප්ටයට එන පරාමිතීන් විග්‍රහ කිරීම සඳහා නිරූපණය භාවිතා කිරීම සඳහාshow_use "$@"
ඔලෙක්සි චෙකුලෙයිව්

මූලික වශයෙන් මම සොයාගත්තා github.com/renatosilva/easyoptions එකම ආකාරයකින් කරන නමුත් මෙම ශ්‍රිතයට වඩා ටිකක් විශාලයි.
ඔලෙක්සි චෙකුලෙව්

10

EasyOptions සඳහා කිසිදු විග්‍රහයක් අවශ්‍ය නොවේ:

## Options:
##   --verbose, -v  Verbose mode
##   --output=FILE  Output filename

source easyoptions || exit

if test -n "${verbose}"; then
    echo "output file is ${output}"
    echo "${arguments[@]}"
fi

ඔබගේ උදාහරණ ස්ක්‍රිප්ටයේ ඉහළින් ඇති අදහස් පෙරනිමි භාවිත උපකාරක නූලක් මෙන්ම තර්ක පිරිවිතරයන් විග්‍රහ කර ඇති බව වටහා ගැනීමට මට විනාඩියක් ගත විය. මෙය දීප්තිමත් විසඳුමක් වන අතර මට කණගාටුයි එයට ලැබුණේ වසර 2 ක් තුළ ඡන්ද 6 ක් පමණි. සමහර විට මෙම ප්‍රශ්නය මිනිසුන්ට නොපෙනෙන තරමට ගිලී ඇත.
Metamorphic

එක් අතකින් ඔබේ විසඳුම වඩාත්ම හොඳය (“සම්මත” විකල්ප වාක්‍ය ඛණ්ඩයට සහය නොදක්වන le ඔලෙක්සි චෙකියුලෙව් හැර). මෙයට හේතුව ඔබේ විසඳුමට පිටපත් රචකයාට අවශ්‍ය වන්නේ එක් එක් විකල්පයේ නම එක් වරක් පමණි . වෙනත් විසඳුම් සඳහා එය 3 වතාවක් නියම කිරීම අවශ්‍ය වේ - භාවිතයේදී, 'සිද්ධි' රටාවේ සහ විචල්‍යය සැකසීමේදී - දිගින් දිගටම මා කෝපයට පත් කළේය. Getopt පවා මෙම ගැටලුව ඇත. කෙසේ වෙතත්, ඔබේ කේතය මගේ යන්ත්‍රයේ මන්දගාමී වේ - බෑෂ් ක්‍රියාත්මක කිරීම සඳහා 0.11s, රූබී සඳහා 0.28s. පැහැදිලි "අතර-නඩුව" විග්‍රහ කිරීම සඳහා 0.02s එදිරිව.
Metamorphic

මට වේගවත් අනුවාදයක් අවශ්‍යයි, සමහර විට සී වලින් ලියා ඇත. එසේම, zsh සමඟ අනුකූල වන අනුවාදයකි. සමහර විට මෙය වෙනම ප්‍රශ්නයක් ලැබීමට සුදුසුයි ("සම්මත දිගු-විකල්ප වාක්‍ය ඛණ්ඩය පිළිගන්නා සහ විකල්ප නම් එක වරකට වඩා ටයිප් කිරීමට අවශ්‍ය නොවන Bash වැනි කවච වල විධාන රේඛා විග්‍රහ කිරීමට ක්‍රමයක් තිබේද?").
Metamorphic

10

ඔබ එය ස්ථාපනය කර ඇති # 1 සහ # 2 ඔබ එකම වේදිකාවක ධාවනය කිරීමට අදහස් කරන්නේ නම් getopts විශිෂ්ට ලෙස ක්‍රියා කරයි. OSX සහ ලිනක්ස් (උදාහරණයක් ලෙස) මේ සම්බන්ධයෙන් වෙනස් ලෙස හැසිරේ.

සමානාත්මතාව, සමාන නොවන සහ බූලියන් ධජ සඳහා සහය දක්වන (නොගැලපෙන) විසඳුමක් මෙන්න. උදාහරණයක් ලෙස ඔබට ඔබේ ස්ක්‍රිප්ට් මේ ආකාරයෙන් ධාවනය කළ හැකිය:

./script --arg1=value1 --arg2 value2 --shouldClean

# parse the arguments.
COUNTER=0
ARGS=("$@")
while [ $COUNTER -lt $# ]
do
    arg=${ARGS[$COUNTER]}
    let COUNTER=COUNTER+1
    nextArg=${ARGS[$COUNTER]}

    if [[ $skipNext -eq 1 ]]; then
        echo "Skipping"
        skipNext=0
        continue
    fi

    argKey=""
    argVal=""
    if [[ "$arg" =~ ^\- ]]; then
        # if the format is: -key=value
        if [[ "$arg" =~ \= ]]; then
            argVal=$(echo "$arg" | cut -d'=' -f2)
            argKey=$(echo "$arg" | cut -d'=' -f1)
            skipNext=0

        # if the format is: -key value
        elif [[ ! "$nextArg" =~ ^\- ]]; then
            argKey="$arg"
            argVal="$nextArg"
            skipNext=1

        # if the format is: -key (a boolean flag)
        elif [[ "$nextArg" =~ ^\- ]] || [[ -z "$nextArg" ]]; then
            argKey="$arg"
            argVal=""
            skipNext=0
        fi
    # if the format has not flag, just a value.
    else
        argKey=""
        argVal="$arg"
        skipNext=0
    fi

    case "$argKey" in 
        --source-scmurl)
            SOURCE_URL="$argVal"
        ;;
        --dest-scmurl)
            DEST_URL="$argVal"
        ;;
        --version-num)
            VERSION_NUM="$argVal"
        ;;
        -c|--clean)
            CLEAN_BEFORE_START="1"
        ;;
        -h|--help|-help|--h)
            showUsage
            exit
        ;;
    esac
done

8

එකවරම ඉහළට කොහේ හරි තැනක ධාවනය වන බිඳවැටීම් වළක්වා ගැනීම සඳහා මම ශ්‍රිතයක් කරන්නේ මෙයයි:

function waitForWeb () {
   local OPTIND=1 OPTARG OPTION
   local host=localhost port=8080 proto=http
   while getopts "h:p:r:" OPTION; do
      case "$OPTION" in
      h)
         host="$OPTARG"
         ;;
      p)
         port="$OPTARG"
         ;;
      r)
         proto="$OPTARG"
         ;;
      esac
   done
...
}

8

@ බ un නෝ-බ්‍රොනොස්කිගේ පිළිතුර පුළුල් කරමින්, පොදු හැඩතල ගැන්වීම් කිහිපයක් හැසිරවීමට මම “පෙර සැකසුම් යන්ත්‍රයක්” එක් කළෙමි:

  • දක්වා --longopt=valපුළුල් වේ--longopt val
  • දක්වා -xyzපුළුල් වේ-x -y -z
  • --කොඩි වල අවසානය දැක්වීමට සහාය දක්වයි
  • අනපේක්ෂිත විකල්ප සඳහා දෝෂයක් පෙන්වයි
  • සංයුක්ත හා පහසුවෙන් කියවිය හැකි විකල්ප මාරුව
#!/bin/bash

# Report usage
usage() {
  echo "Usage:"
  echo "$(basename $0) [options] [--] [file1, ...]"

  # Optionally exit with a status code
  if [ -n "$1" ]; then
    exit "$1"
  fi
}

invalid() {
  echo "ERROR: Unrecognized argument: $1" >&2
  usage 1
}

# Pre-process options to:
# - expand -xyz into -x -y -z
# - expand --longopt=arg into --longopt arg
ARGV=()
END_OF_OPT=
while [[ $# -gt 0 ]]; do
  arg="$1"; shift
  case "${END_OF_OPT}${arg}" in
    --) ARGV+=("$arg"); END_OF_OPT=1 ;;
    --*=*)ARGV+=("${arg%%=*}" "${arg#*=}") ;;
    --*) ARGV+=("$arg"); END_OF_OPT=1 ;;
    -*) for i in $(seq 2 ${#arg}); do ARGV+=("-${arg:i-1:1}"); done ;;
    *) ARGV+=("$arg") ;;
  esac
done

# Apply pre-processed options
set -- "${ARGV[@]}"

# Parse options
END_OF_OPT=
POSITIONAL=()
while [[ $# -gt 0 ]]; do
  case "${END_OF_OPT}${1}" in
    -h|--help)      usage 0 ;;
    -p|--password)  shift; PASSWORD="$1" ;;
    -u|--username)  shift; USERNAME="$1" ;;
    -n|--name)      shift; names+=("$1") ;;
    -q|--quiet)     QUIET=1 ;;
    -C|--copy)      COPY=1 ;;
    -N|--notify)    NOTIFY=1 ;;
    --stdin)        READ_STDIN=1 ;;
    --)             END_OF_OPT=1 ;;
    -*)             invalid "$1" ;;
    *)              POSITIONAL+=("$1") ;;
  esac
  shift
done

# Restore positional parameters
set -- "${POSITIONAL[@]}"

6

Cmdline args විග්‍රහ කිරීමට ක්‍රම කිහිපයක් තිබේ (උදා: GNU getopt (අතේ ගෙන යා නොහැකි) vs BSD (OSX) getopt vs getopts) - සියල්ල ගැටළු සහගතය. මෙම විසඳුම වේ

  • අතේ ගෙන යා හැකි!
  • ශුන්‍ය පරායත්තතා ඇත, රඳා පවතින්නේ බාෂ් බිල්ට් මත පමණි
  • කෙටි හා දිගු විකල්ප දෙකටම ඉඩ දෙයි
  • විකල්පය සහ තර්කය අතර අවකාශය හසුරුවන නමුත් =බෙදුම්කරු භාවිතා කළ හැකිය
  • සංයුක්ත කෙටි විකල්ප ශෛලියට සහය දක්වයි -vxf
  • විකල්ප තර්ක සමඟ විකල්පය හසුරුවයි (උදාහරණය බලන්න), සහ
  • එකම විශේෂාංග කට්ටලයක් සඳහා විකල්ප සමඟ සසඳන විට කේත පිපිරීමක් අවශ්‍ය නොවේ. එනම් සාරාංශගත බැවින් නඩත්තු කිරීමට පහසුය

උදාහරණ: ඕනෑම

# flag
-f
--foo

# option with required argument
-b"Hello World"
-b "Hello World"
--bar "Hello World"
--bar="Hello World"

# option with optional argument
--baz
--baz="Optional Hello"

#!/usr/bin/env bash

usage() {
  cat - >&2 <<EOF
NAME
    program-name.sh - Brief description

SYNOPSIS
    program-name.sh [-h|--help]
    program-name.sh [-f|--foo]
                    [-b|--bar <arg>]
                    [--baz[=<arg>]]
                    [--]
                    FILE ...

REQUIRED ARGUMENTS
  FILE ...
          input files

OPTIONS
  -h, --help
          Prints this and exits

  -f, --foo
          A flag option

  -b, --bar <arg>
          Option requiring an argument <arg>

  --baz[=<arg>]
          Option that has an optional argument <arg>. If <arg>
          is not specified, defaults to 'DEFAULT'
  --     
          Specify end of options; useful if the first non option
          argument starts with a hyphen

EOF
}

fatal() {
    for i; do
        echo -e "${i}" >&2
    done
    exit 1
}

# For long option processing
next_arg() {
    if [[ $OPTARG == *=* ]]; then
        # for cases like '--opt=arg'
        OPTARG="${OPTARG#*=}"
    else
        # for cases like '--opt arg'
        OPTARG="${args[$OPTIND]}"
        OPTIND=$((OPTIND + 1))
    fi
}

# ':' means preceding option character expects one argument, except
# first ':' which make getopts run in silent mode. We handle errors with
# wildcard case catch. Long options are considered as the '-' character
optspec=":hfb:-:"
args=("" "$@")  # dummy first element so $1 and $args[1] are aligned
while getopts "$optspec" optchar; do
    case "$optchar" in
        h) usage; exit 0 ;;
        f) foo=1 ;;
        b) bar="$OPTARG" ;;
        -) # long option processing
            case "$OPTARG" in
                help)
                    usage; exit 0 ;;
                foo)
                    foo=1 ;;
                bar|bar=*) next_arg
                    bar="$OPTARG" ;;
                baz)
                    baz=DEFAULT ;;
                baz=*) next_arg
                    baz="$OPTARG" ;;
                -) break ;;
                *) fatal "Unknown option '--${OPTARG}'" "see '${0} --help' for usage" ;;
            esac
            ;;
        *) fatal "Unknown option: '-${OPTARG}'" "See '${0} --help' for usage" ;;
    esac
done

shift $((OPTIND-1))

if [ "$#" -eq 0 ]; then
    fatal "Expected at least one required argument FILE" \
    "See '${0} --help' for usage"
fi

echo "foo=$foo, bar=$bar, baz=$baz, files=${@}"

5

මගේ විකල්ප විග්‍රහයේ අනුවාදය ඉදිරිපත් කිරීමට මම කැමතියි, එය පහත සඳහන් දේ සඳහා ඉඩ දෙයි:

-s p1
--stage p1
-w somefolder
--workfolder somefolder
-sw p1 somefolder
-e=hello

මේ සඳහා ද ඉඩ ලබා දේ (අනවශ්‍ය විය හැකිය):

-s--workfolder p1 somefolder
-se=hello p1
-swe=hello p1 somefolder

= විකල්පයක් මත = භාවිතා කළ යුතුද නැද්ද යන්න භාවිතා කිරීමට පෙර ඔබ තීරණය කළ යුතුය. මෙය කේතය පිරිසිදුව තබා ගැනීමයි (ඊෂ්).

while [[ $# > 0 ]]
do
    key="$1"
    while [[ ${key+x} ]]
    do
        case $key in
            -s*|--stage)
                STAGE="$2"
                shift # option has parameter
                ;;
            -w*|--workfolder)
                workfolder="$2"
                shift # option has parameter
                ;;
            -e=*)
                EXAMPLE="${key#*=}"
                break # option has been fully handled
                ;;
            *)
                # unknown option
                echo Unknown option: $key #1>&2
                exit 10 # either this: my preferred way to handle unknown options
                break # or this: do this to signal the option has been handled (if exit isn't used)
                ;;
        esac
        # prepare for next option in this key, if any
        [[ "$key" = -? || "$key" == --* ]] && unset key || key="${key/#-?/-}"
    done
    shift # option(s) fully processed, proceed to next input argument
done

1
+ {key + x on හි "+ x" යන්නෙහි තේරුම කුමක්ද?
ලූකා ඩවාන්සෝ

1
'යතුර' තිබේද නැද්ද යන්න පරීක්ෂා කිරීමකි. තව දුරටත් මම යතුර සකසා නැති අතර මෙය ඇතුළත ලූපය බිඳ දමයි.
galmok

5

පාලනය කළ නොහැකි තර්ක ආරක්ෂා කරන විසඳුම. ආදර්ශන ඇතුළත්.

මෙන්න මගේ විසඳුම. එය ඉතා නම්‍යශීලී වන අතර අනෙක් ඒවා මෙන් නොව බාහිර පැකේජ අවශ්‍ය නොවිය යුතු අතර ඉතිරි තර්ක පිරිසිදු ලෙස හැසිරවිය යුතුය.

භාවිතය: ./myscript -flag flagvariable -otherflag flagvar2

ඔබ කළ යුත්තේ වලංගු ෆ්ලෑග් රේඛාව සංස්කරණය කිරීම පමණි. එය යටි ඉරක් සකස් කර සියලු තර්ක සොයයි. එය ඊළඟ තර්කය ධජ නාමය ලෙස අර්ථ දක්වයි

./myscript -flag flagvariable -otherflag flagvar2
echo $flag $otherflag
flagvariable flagvar2

ප්‍රධාන කේතය (කෙටි අනුවාදය, නිදසුන් සහිත වාචික තව දුරටත් පහළට, දෝෂ සහිත අනුවාදයක්):

#!/usr/bin/env bash
#shebang.io
validflags="rate time number"
count=1
for arg in $@
do
    match=0
    argval=$1
    for flag in $validflags
    do
        sflag="-"$flag
        if [ "$argval" == "$sflag" ]
        then
            declare $flag=$2
            match=1
        fi
    done
        if [ "$match" == "1" ]
    then
        shift 2
    else
        leftovers=$(echo $leftovers $argval)
        shift
    fi
    count=$(($count+1))
done
#Cleanup then restore the leftovers
shift $#
set -- $leftovers

බිල්ට් එකෝ ඩිමෝස් සමඟ වාචික අනුවාදය:

#!/usr/bin/env bash
#shebang.io
rate=30
time=30
number=30
echo "all args
$@"
validflags="rate time number"
count=1
for arg in $@
do
    match=0
    argval=$1
#   argval=$(echo $@ | cut -d ' ' -f$count)
    for flag in $validflags
    do
            sflag="-"$flag
        if [ "$argval" == "$sflag" ]
        then
            declare $flag=$2
            match=1
        fi
    done
        if [ "$match" == "1" ]
    then
        shift 2
    else
        leftovers=$(echo $leftovers $argval)
        shift
    fi
    count=$(($count+1))
done

#Cleanup then restore the leftovers
echo "pre final clear args:
$@"
shift $#
echo "post final clear args:
$@"
set -- $leftovers
echo "all post set args:
$@"
echo arg1: $1 arg2: $2

echo leftovers: $leftovers
echo rate $rate time $time number $number

අවසාන එක, වලංගු නොවන ආරෝපණයක් සම්මත වුවහොත් මෙය වැරදී යයි.

#!/usr/bin/env bash
#shebang.io
rate=30
time=30
number=30
validflags="rate time number"
count=1
for arg in $@
do
    argval=$1
    match=0
        if [ "${argval:0:1}" == "-" ]
    then
        for flag in $validflags
        do
                sflag="-"$flag
            if [ "$argval" == "$sflag" ]
            then
                declare $flag=$2
                match=1
            fi
        done
        if [ "$match" == "0" ]
        then
            echo "Bad argument: $argval"
            exit 1
        fi
        shift 2
    else
        leftovers=$(echo $leftovers $argval)
        shift
    fi
    count=$(($count+1))
done
#Cleanup then restore the leftovers
shift $#
set -- $leftovers
echo rate $rate time $time number $number
echo leftovers: $leftovers

වාසි: එය කරන දේ, එය ඉතා හොඳින් හසුරුවයි. මෙහි ඇති වෙනත් විසඳුම් බොහොමයක් භාවිතා නොකරන භාවිතයට නොගත් තර්ක එය ආරක්ෂා කරයි. ස්ක්‍රිප්ටයේ අතින් නිර්වචනය නොකර විචල්‍යයන් කැඳවීමට ද එය ඉඩ දෙයි. අනුරූප තර්කයක් ලබා නොදුනහොත් විචල්‍යයන් පූර්ව සැකසීමට ද එය ඉඩ දෙයි. (වාචික උදාහරණය බලන්න).

අවාසි: තනි සංකීර්ණ තර්ක මාලාවක් විග්‍රහ කළ නොහැක. උදා: -xcvf තනි තර්කයක් ලෙස ක්‍රියා කරයි. මෙම ක්‍රියාකාරිත්වය එකතු කරන අමතර කේතයක් ඔබට පහසුවෙන් ලිවිය හැකිය.


5

මට මගේ ව්‍යාපෘතිය ඉදිරිපත් කිරීමට අවශ්‍යයි: https://github.com/flyingangel/argparser

source argparser.sh
parse_args "$@"

ඒ තරම් සරළයි. පරිසරය තර්ක වලට සමාන නමක් සහිත විචල්‍යයන්ගෙන් පිරී යයි


3

එය සටහන් කර ගන්න getopt(1)එය AT&T වෙතින් කෙටි කාලීන වැරැද්දක් .

getopt 1984 දී නිර්මාණය කරන ලද නමුත් දැනටමත් 1986 දී වළලනු ලැබුවේ එය සැබවින්ම භාවිතයට ගත නොහැකි බැවිනි.

getoptඉතා යල්පැන ඇති බවට සාක්ෂියක් නම් , 1986 දී බෝර්න් ෂෙල් එකට එකතු කරන ලද ඒ වෙනුවට getopt(1)මෑන් පිටුවෙහි තවමත් සඳහන් වී ඇති බවයි."$*""$@"getopts(1) ඇතුළත අවකාශයන් සමඟ තර්ක සමඟ කටයුතු කිරීම සඳහා ෂෙල් බිල්ඩින් සමඟ ය.

BTW: ඔබ ෂෙල් ස්ක්‍රිප්ට් වල දිගු විකල්ප විග්‍රහ කිරීමට කැමති නම්, getopt(3)libc (Solaris) වෙතින් ක්‍රියාත්මක කිරීම සහ ksh93දෙකම කෙටි විකල්ප සඳහා අන්වර්ථ නාමයන් ලෙස දිගු විකල්ප සඳහා සහාය වන ඒකාකාර දිගු විකල්ප ක්‍රියාත්මක කිරීමක් එකතු කර ඇති බව දැන ගැනීමට උනන්දු විය හැකිය . මෙම හේතු ksh93සහ Bourne Shellහරහා දිගු විකල්ප සඳහා නිල ඇඳුමක් අතුරු මුහුණත ක්රියාත්මක කිරීමටgetopts .

බෝර්න් ෂෙල් මෑන් පිටුවෙන් ලබාගත් දිගු විකල්ප සඳහා උදාහරණයක්:

getopts "f:(file)(input-file)o:(output-file)" OPTX "$@"

බෝර්න් ෂෙල් සහ ksh93 යන දෙවර්ගයේම විකල්ප අන්වර්ථයන් කොපමණ කාලයක් භාවිතා කළ හැකිදැයි පෙන්වයි.

මෑතදී බෝර්න් ෂෙල් එකක මෑන් පිටුව බලන්න:

http://schillix.sourceforge.net/man/man1/bosh.1.html

සහ OpenSolaris වෙතින් getopt (3) සඳහා වන මෑන් පිටුව:

http://schillix.sourceforge.net/man/man3c/getopt.3c.html

අවසාන වශයෙන්, යල් පැන ගිය $ * සත්‍යාපනය සඳහා getopt (1) man පිටුව:

http://schillix.sourceforge.net/man/man1/getopt.1.html


3

ලස්සන බාෂ් මෙවලමක් ලිවීමට මම බාෂ් සහායකයකු ලියා ඇත

ව්‍යාපෘති නිවස: https://gitlab.mbedsys.org/mbedsys/bashopts

උදාහරණයක්:

#!/bin/bash -ei

# load the library
. bashopts.sh

# Enable backtrace dusplay on error
trap 'bashopts_exit_handle' ERR

# Initialize the library
bashopts_setup -n "$0" -d "This is myapp tool description displayed on help message" -s "$HOME/.config/myapprc"

# Declare the options
bashopts_declare -n first_name -l first -o f -d "First name" -t string -i -s -r
bashopts_declare -n last_name -l last -o l -d "Last name" -t string -i -s -r
bashopts_declare -n display_name -l display-name -t string -d "Display name" -e "\$first_name \$last_name"
bashopts_declare -n age -l number -d "Age" -t number
bashopts_declare -n email_list -t string -m add -l email -d "Email adress"

# Parse arguments
bashopts_parse_args "$@"

# Process argument
bashopts_process_args

උදව් ලබා දෙනු ඇත:

NAME:
    ./example.sh - This is myapp tool description displayed on help message

USAGE:
    [options and commands] [-- [extra args]]

OPTIONS:
    -h,--help                          Display this help
    -n,--non-interactive true          Non interactive mode - [$bashopts_non_interactive] (type:boolean, default:false)
    -f,--first "John"                  First name - [$first_name] (type:string, default:"")
    -l,--last "Smith"                  Last name - [$last_name] (type:string, default:"")
    --display-name "John Smith"        Display name - [$display_name] (type:string, default:"$first_name $last_name")
    --number 0                         Age - [$age] (type:number, default:0)
    --email                            Email adress - [$email_list] (type:string, default:"")

විනෝද වන්න :)


මම මෙය මැක් ඕඑස් එක්ස් වෙතින් ලබා ගනිමි: `` `lib / bashopts.sh: 138 වන පේළිය: ප්‍රකාශ කරන්න: -ඒ: අවලංගු විකල්පය ප්‍රකාශ කරන්න: භාවිතය: ප්‍රකාශ කරන්න [-afFirtx] [-p] [නම [= අගය] ...] Lib / bashopts.sh හි දෝෂයකි: 138. 'ප්‍රකාශ කරන්න -x -A bashopts_optprop_name' තත්වය 2 සමඟ පිටවී ඇත ඇමතුම් ගස: 1: lib / controller.sh: 4 ප්‍රභවය (...) තත්වය 1 සමඟ පිටවීම `` `
ජොෂ් වුල්ෆ්

මෙය භාවිතා කිරීමට ඔබට Bash අනුවාදය 4 අවශ්‍ය වේ. මැක්හි, පෙරනිමි අනුවාදය 3 වේ. ඔබට බාෂ් 4 ස්ථාපනය කිරීම සඳහා ගෘහස්ථ බීර භාවිතා කළ හැකිය.
ජොෂ් වුල්ෆ්

3

මෙන්න මගේ ප්රවේශය - regexp භාවිතා කිරීම.

  • ගෙටොප් නැත
  • එය කෙටි පරාමිතීන් අවහිර කරයි -qwerty
  • එය කෙටි පරාමිතීන් හසුරුවයි -q -w -e
  • එය දිගු විකල්පයන් හසුරුවයි --qwerty
  • ඔබට කෙටි හෝ දිගු විකල්පයකට ගුණාංගය යැවිය හැකිය (ඔබ කෙටි විකල්ප වාරණයක් භාවිතා කරන්නේ නම්, ගුණාංගය අවසාන විකල්පයට අමුණා ඇත)
  • ඔබට අවකාශයන් භාවිතා කිරීමට හෝ =ගුණාංග සැපයීමට හැකිය, නමුත් යටි ඉර + අවකාශය “පරිසීමකය” හමු වන තෙක් ගැලපීම් ආරෝපණය කරන්න, එබැවින් --q=qwe ty qwe tyඑක් ගුණාංගයකි
  • එය ඉහත සියල්ල මිශ්‍ර කිරීම හසුරුවන බැවින් -o a -op attr ibute --option=att ribu te --op-tion attribute --option att-ributeවලංගු වේ

පිටපත:

#!/usr/bin/env sh

help_menu() {
  echo "Usage:

  ${0##*/} [-h][-l FILENAME][-d]

Options:

  -h, --help
    display this help and exit

  -l, --logfile=FILENAME
    filename

  -d, --debug
    enable debug
  "
}

parse_options() {
  case $opt in
    h|help)
      help_menu
      exit
     ;;
    l|logfile)
      logfile=${attr}
      ;;
    d|debug)
      debug=true
      ;;
    *)
      echo "Unknown option: ${opt}\nRun ${0##*/} -h for help.">&2
      exit 1
  esac
}
options=$@

until [ "$options" = "" ]; do
  if [[ $options =~ (^ *(--([a-zA-Z0-9-]+)|-([a-zA-Z0-9-]+))(( |=)(([\_\.\?\/\\a-zA-Z0-9]?[ -]?[\_\.\?a-zA-Z0-9]+)+))?(.*)|(.+)) ]]; then
    if [[ ${BASH_REMATCH[3]} ]]; then # for --option[=][attribute] or --option[=][attribute]
      opt=${BASH_REMATCH[3]}
      attr=${BASH_REMATCH[7]}
      options=${BASH_REMATCH[9]}
    elif [[ ${BASH_REMATCH[4]} ]]; then # for block options -qwert[=][attribute] or single short option -a[=][attribute]
      pile=${BASH_REMATCH[4]}
      while (( ${#pile} > 1 )); do
        opt=${pile:0:1}
        attr=""
        pile=${pile/${pile:0:1}/}
        parse_options
      done
      opt=$pile
      attr=${BASH_REMATCH[7]}
      options=${BASH_REMATCH[9]}
    else # leftovers that don't match
      opt=${BASH_REMATCH[10]}
      options=""
    fi
    parse_options
  fi
done

මේක වගේ. සමහර විට නව රේඛාවක් සමඟ ප්‍රතිරාවය කිරීමට -e පරාමිතිය එක් කරන්න.
mauron85

3

අපි නම් ෂෙල් තිර රචනය නිර්මාණය උපකල්පනය test_args.shපහත සඳහන් පරිදි

#!/bin/sh
until [ $# -eq 0 ]
do
  name=${1:1}; shift;
  if [[ -z "$1" || $1 == -* ]] ; then eval "export $name=true"; else eval "export $name=$1"; shift; fi  
done
echo "year=$year month=$month day=$day flag=$flag"

අපි පහත විධානය ක්‍රියාත්මක කිරීමෙන් පසු:

sh test_args.sh  -year 2017 -flag  -month 12 -day 22 

ප්‍රතිදානය වනුයේ:

year=2017 month=12 day=22 flag=true

5
මෙය නෝවාගේ පිළිතුරට සමාන ප්‍රවේශයක් ගනී , නමුත් අඩු ආරක්‍ෂිත චෙක්පත් / ආරක්ෂණ ඇත. මෙය අපට ස්ක්‍රිප්ට් පරිසරයට අත්තනෝමතික තර්ක ලිවීමට ඉඩ සලසයි. ඔබ විශ්වාස කරන පරිදි ඔබ මෙහි එවාල් භාවිතා කිරීම විධාන එන්නත් කිරීමට ඉඩ දෙනු ඇත.
විල් බාර්න්වෙල්

3

මෙන්න අවම කේතයක් සමඟ විග්‍රහ කිරීම සාක්ෂාත් කර ගන්නා අතර එක් අවස්ථාවක දී උපුටා ගැනීම සමඟ උපස්ථරය භාවිතා කරමින් අර්ථ දැක්වීමට ඔබට ඉඩ සලසයි.

මූලික වශයෙන් eval "local key='val'"

function myrsync() {

        local backup=("${@}") args=(); while [[ $# -gt 0 ]]; do k="$1";
                case "$k" in
                    ---sourceuser|---sourceurl|---targetuser|---targeturl|---file|---exclude|---include)
                        eval "local ${k:3}='${2}'"; shift; shift    # Past two arguments
                    ;;
                    *)  # Unknown option  
                        args+=("$1"); shift;                        # Past argument only
                    ;;                                              
                esac                                                
        done; set -- "${backup[@]}"                                 # Restore $@


        echo "${sourceurl}"
}

මෙහි බොහෝ පිළිතුරු ලෙස ගෝලීයයන් වෙනුවට විචල්‍යයන් දේශීයයන් ලෙස ප්‍රකාශ කරයි.

ලෙස හැඳින්වේ:

myrsync ---sourceurl http://abc.def.g ---sourceuser myuser ... 

$ {K: 3 basic මූලික වශයෙන් ---යතුරෙන් ඉවත් කිරීමට උපස්ථරයකි .



2

ස්ථානීය සහ ධජ මත පදනම් වූ තර්ක මිශ්‍ර කිරීම

--param = arg (සමානව වෙන් කර ඇත)

ස්ථානීය තර්ක අතර කොඩි නිදහසේ මිශ්‍ර කිරීම:

./script.sh dumbo 127.0.0.1 --environment=production -q -d
./script.sh dumbo --environment=production 127.0.0.1 --quiet -d

තරමක් සංක්ෂිප්ත ප්‍රවේශයකින් ඉටු කළ හැකිය:

# process flags
pointer=1
while [[ $pointer -le $# ]]; do
   param=${!pointer}
   if [[ $param != "-"* ]]; then ((pointer++)) # not a parameter flag so advance pointer
   else
      case $param in
         # paramter-flags with arguments
         -e=*|--environment=*) environment="${param#*=}";;
                  --another=*) another="${param#*=}";;

         # binary flags
         -q|--quiet) quiet=true;;
                 -d) debug=true;;
      esac

      # splice out pointer frame from positional list
      [[ $pointer -gt 1 ]] \
         && set -- ${@:1:((pointer - 1))} ${@:((pointer + 1)):$#} \
         || set -- ${@:((pointer + 1)):$#};
   fi
done

# positional remain
node_name=$1
ip_address=$2

--param arg (අවකාශය වෙන් කර ඇත)

මිශ්‍ර කිරීම --flag=valueහා --flag valueමෝස්තර නොකිරීම සාමාන්‍ය දෙයකි .

./script.sh dumbo 127.0.0.1 --environment production -q -d

මෙය කියවීමට ටිකක් ඩයිසි, නමුත් තවමත් වලංගු වේ

./script.sh dumbo --environment production 127.0.0.1 --quiet -d

මූලාශ්රය

# process flags
pointer=1
while [[ $pointer -le $# ]]; do
   if [[ ${!pointer} != "-"* ]]; then ((pointer++)) # not a parameter flag so advance pointer
   else
      param=${!pointer}
      ((pointer_plus = pointer + 1))
      slice_len=1

      case $param in
         # paramter-flags with arguments
         -e|--environment) environment=${!pointer_plus}; ((slice_len++));;
                --another) another=${!pointer_plus}; ((slice_len++));;

         # binary flags
         -q|--quiet) quiet=true;;
                 -d) debug=true;;
      esac

      # splice out pointer frame from positional list
      [[ $pointer -gt 1 ]] \
         && set -- ${@:1:((pointer - 1))} ${@:((pointer + $slice_len)):$#} \
         || set -- ${@:((pointer + $slice_len)):$#};
   fi
done

# positional remain
node_name=$1
ip_address=$2

2

විග්‍රහ කිරීමේ විකල්ප සඳහා මා විසින් සාදන ලද දේ බෙදා ගැනීමට මට අවශ්‍ය විය. මෙහි ඇති පිළිතුරු මගින් මගේ සමහර අවශ්‍යතා (උපසිරැසි කළමනාකරණය, var args, විකල්ප ආග් ආදිය) සපුරා නොතිබුණි, එබැවින් මට මෙය ඉදිරිපත් කිරීමට සිදුවිය: https://github.com/MihirLuthra/bash_option_parser

fruitපහත දැක්වෙන පරිදි භාවිතයෙන් නම් කරන ලද විධානයක් අපට ඇතැයි කියමු :

fruit ...
   [-e|—-eat|—-chew]
   [-c|--cut <how> <why>]
   <command> [<args>] 

-eකිසිදු args ගනී
-cargs දෙකක් එනම් සැපයුම අත්හිටුවන ඇයි කැපූ ආකාරය ගනී
<command>වැනි suboptions සඳහා apple, orange(සමාන ආදිය gitsuboptions ඇති commit, pushආදිය)

එබැවින් එය විග්‍රහ කිරීමට:

source ./option_parser

parse_options \
    ',' 'OPTIONS' 'ARG_CNT' 'ARGS' 'self' '0' ';' '--'  \
                                                        \
    '-e'    , '—-eat' , '—-chew'  '0'                   \
    '-c'    , '—-cut' ,           '1 1'                 \
    'apple'                       'S'                   \
    'orange'                      'S'                   \
                                                        \
    ';' "$@"

දැන් කිසියම් භාවිත දෝෂයක් තිබේ නම්, එය option_parser_error_msgපහත පරිදි මුද්‍රණය කළ හැකිය :

retval=$?

if [ $retval -ne 0 ]; then
    option_parser_error_msg "$retval" 'OPTIONS'
    exit 1
fi

සමහර විකල්ප සම්මත වී ඇත්දැයි දැන් පරීක්ෂා කිරීමට,

if [ -n "${OPTIONS[-c]}" ]
then
    echo "-c was passed"

    # args can be accessed in a 2D-array-like format
    echo "Arg1 to -c = ${ARGS[-c,0]}"
    echo "Arg2 to -c = ${ARGS[-c,1]}"

fi

උපසිරැසියක් සඳහා, appleකාගේ භාවිතය වගේ:

fruit apple ...
   [—-eat-apple|—-chew-apple]
   [-p|—-peel <how>] 

එය සම්මත වී ඇත්දැයි අපට පරීක්ෂා කර පහත පරිදි විග්‍රහ කළ හැකිය:

if [ -n "${OPTION[apple]}" ]
then
    shift_count=${OPTION[apple]}

    parse_options \
    ',' 'OPTIONS_apple' 'ARG_CNT_apple' 'ARGS_apple'    \
    'self' "$shift_count" ';' '--'                      \
                                                        \
    '—-eat-apple' , '—-chew-apple'  '0'                 \
    '-p'          , '—-peel'        '1'                 \
                                                        \
    ';' "$@"

fi

උපසිරැසි විග්‍රහ කිරීම සිදු කරනුයේ $shift_countවෙත යාමෙනිparse_options එය suboption ක args ළඟා args මාරු පසු මාණකරනය ක්රියාත්මක ආරම්භ කරයි.

සවිස්තරාත්මක විස්තරයක් රීඩ්මේ සහ නිධියේ උදාහරණ වලින් දක්වා ඇත .


1

මෙය දැන ගැනීමටද ප්‍රයෝජනවත් විය හැකිය, ඔබට අගයක් සැකසිය හැකි අතර යමෙකු ආදානය ලබා දෙන්නේ නම්, එම අගය සමඟ පෙරනිමිය අභිබවා යන්න ..

myscript.sh -f ./serverlist.txt හෝ ./myscript.sh (එය පෙරනිමි ගනී)

    #!/bin/bash
    # --- set the value, if there is inputs, override the defaults.

    HOME_FOLDER="${HOME}/owned_id_checker"
    SERVER_FILE_LIST="${HOME_FOLDER}/server_list.txt"

    while [[ $# > 1 ]]
    do
    key="$1"
    shift

    case $key in
        -i|--inputlist)
        SERVER_FILE_LIST="$1"
        shift
        ;;
    esac
    done


    echo "SERVER LIST   = ${SERVER_FILE_LIST}"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.