args.sh(文件已创建)
@@ -0,0 +1,158 @@ | |||
1 | + | #!/usr/bin/env bash | |
2 | + | ||
3 | + | # Argument parser for bash scripts | |
4 | + | # | |
5 | + | # Author: Anthony Axenov (Антон Аксенов) | |
6 | + | # Version: 1.6 | |
7 | + | # License: MIT | |
8 | + | # Description: https://git.axenov.dev/anthony/shell/src/branch/master/helpers/arg-parser | |
9 | + | ||
10 | + | #purpose Little helper to check if string matches PCRE | |
11 | + | #argument $1 - some string | |
12 | + | #argument $2 - regex | |
13 | + | #exitcode 0 - string valid | |
14 | + | #exitcode 1 - string is not valid | |
15 | + | grep_match() { | |
16 | + | printf "%s" "$1" | grep -qE "$2" >/dev/null | |
17 | + | } | |
18 | + | ||
19 | + | #purpose Find short argument or its value | |
20 | + | #argument $1 - (string) argument (without leading dashes; only first letter will be processed) | |
21 | + | #argument $2 - (number) is it flag? 1 if is, otherwise 0 or nothing | |
22 | + | #argument $3 - (string) variable to return value into | |
23 | + | # (if not specified then it will be echo'ed in stdout) | |
24 | + | #returns (string) 1 (if $2 == 1), value (if correct and if $2 != 1) or nothing | |
25 | + | #usage To get value into var: arg v 0 myvar or myvalue=$(arg 'v') | |
26 | + | #usage To find flag into var: arg f 1 myvar or flag=$(arg 'f') | |
27 | + | #usage To echo value: arg v | |
28 | + | #usage To echo 1 if flag exists: arg f | |
29 | + | arg() { | |
30 | + | [ "$1" ] || { echo "Argument name is not specified!" >&2 && exit 1; } | |
31 | + | local arg_name="${1:0:1}" # first character of argument name to find | |
32 | + | local is_flag="$2" || 0 # 1 if we need just find a flag, 0 to get a value | |
33 | + | local var_name="$3" || 0 # variable name to return value into or 0 to echo it in stdout | |
34 | + | local value= # initialize empty value to check if we found one later | |
35 | + | local arg_found=0 # marker of found argument | |
36 | + | ||
37 | + | for idx in "${!__RAW_ARGS__[@]}"; do # going through all args | |
38 | + | local arg_search=${__RAW_ARGS__[idx]} # get current argument | |
39 | + | ||
40 | + | # skip $arg_search if it starts with '--' or letter | |
41 | + | grep_match "$arg_search" "^(\w|--)" && continue | |
42 | + | ||
43 | + | # clear $arg_search from special and duplicate characters, e.g. 'fas-)dfs' will become 'fasd' | |
44 | + | local arg_chars="$(printf "%s" "$arg_search" \ | |
45 | + | | tr -s "[$arg_search]" 2>/dev/null \ | |
46 | + | | tr -d "[:punct:][:blank:]" 2>/dev/null)" | |
47 | + | ||
48 | + | # if $arg_name is not one of $arg_chars the skip it | |
49 | + | grep_match "-$arg_name" "^-[$arg_chars]$" || continue | |
50 | + | arg_found=1 | |
51 | + | ||
52 | + | # then return '1'|'0' back into $value if we need flag or next arg value otherwise | |
53 | + | [ "$is_flag" = 1 ] && value=1 || value="${__RAW_ARGS__[idx+1]}" | |
54 | + | break | |
55 | + | done | |
56 | + | ||
57 | + | [ "$is_flag" = 1 ] && [ -z "$value" ] && value=0; | |
58 | + | ||
59 | + | # if value we found is empty or looks like another argument then exit with error message | |
60 | + | if [ "$arg_found" = 1 ] && ! grep_match "$value" "^[[:graph:]]+$" || grep_match "$value" "^--?\w+$"; then | |
61 | + | echo "ERROR: Argument '-$arg_name' must have correct value!" >&2 && exit 1 | |
62 | + | fi | |
63 | + | ||
64 | + | # return '$value' back into $var_name (if exists) or echo in stdout | |
65 | + | [ "$var_name" ] && eval "$var_name='$value'" || echo "$value" | |
66 | + | } | |
67 | + | ||
68 | + | #purpose Find long argument or its value | |
69 | + | #argument $1 - argument (without leading dashes) | |
70 | + | #argument $2 - (number) is it flag? 1 if is, otherwise 0 or nothing | |
71 | + | #argument $3 - (string) variable to return value into | |
72 | + | # (if not specified then it will be echo'ed in stdout) | |
73 | + | #returns (string) 1 (if $2 == 1), value (if correct and if $2 != 1) or nothing | |
74 | + | #usage To get value into var: arg v 0 myvar or myvalue=$(arg 'v') | |
75 | + | #usage To find flag into var: arg f 1 myvar or flag=$(arg 'f') | |
76 | + | #usage To echo value: arg v | |
77 | + | #usage To echo 1 if flag exists: arg f | |
78 | + | argl() { | |
79 | + | [ "$1" ] || { echo "Argument name is not specified!" >&2 && exit 1; } | |
80 | + | local arg_name="$1" # argument name to find | |
81 | + | local is_flag="$2" || 0 # 1 if we need just find a flag, 0 to get a value | |
82 | + | local var_name="$3" || 0 # variable name to return value into or 0 to echo it in stdout | |
83 | + | local value= # initialize empty value to check if we found one later | |
84 | + | local arg_found=0 # marker of found argument | |
85 | + | ||
86 | + | for idx in "${!__RAW_ARGS__[@]}"; do # going through all args | |
87 | + | local arg_search="${__RAW_ARGS__[idx]}" # get current argument | |
88 | + | ||
89 | + | if [ "$arg_search" = "--$arg_name" ]; then # if current arg begins with two dashes | |
90 | + | # then return '1' back into $value if we need flag or next arg value otherwise | |
91 | + | [ "$is_flag" = 1 ] && value=1 || value="${__RAW_ARGS__[idx+1]}" | |
92 | + | break # stop the loop | |
93 | + | elif grep_match "$arg_search" "^--$arg_name=.+$"; then # check if $arg like '--foo=bar' | |
94 | + | # then return '1' back into $value if we need flag or part from '=' to arg's end as value otherwise | |
95 | + | [ "$is_flag" = 1 ] && value=1 || value="${arg_search#*=}" | |
96 | + | break # stop the loop | |
97 | + | fi | |
98 | + | done | |
99 | + | ||
100 | + | [ "$is_flag" = 1 ] && [ -z "$value" ] && value=0; | |
101 | + | ||
102 | + | # if value we found is empty or looks like another argument then exit with error message | |
103 | + | if [ "$arg_found" = 1 ] && ! grep_match "$value" "^[[:graph:]]+$" || grep_match "$value" "^--?\w+$"; then | |
104 | + | echo "ERROR: Argument '--$arg_name' must have correct value!" >&2 && exit 1; | |
105 | + | fi | |
106 | + | ||
107 | + | # return '$value' back into $var_name (if exists) or echo in stdout | |
108 | + | [ "$var_name" ] && eval "$var_name='$value'" || echo "$value" | |
109 | + | } | |
110 | + | ||
111 | + | ################################ | |
112 | + | ||
113 | + | # This is simple examples which you can play around with. | |
114 | + | # 1. uncomment code below | |
115 | + | # 2. call thi sscript to see what happens: | |
116 | + | # /args.sh -abcd --flag1 --flag2 -e evalue -f fvalue --arg1=value1 --arg2 value2 | |
117 | + | ||
118 | + | # __RAW_ARGS__=("$@") | |
119 | + | ||
120 | + | # arg a 1 flag_a | |
121 | + | # echo "Flag -a has value '$flag_a'" | |
122 | + | # echo "Flag -a has value '$(arg a 1)'" | |
123 | + | ||
124 | + | # arg b 1 flag_b | |
125 | + | # echo "Flag -b has value '$flag_b'" | |
126 | + | # echo "Flag -b has value '$(arg b 1)'" | |
127 | + | ||
128 | + | # arg c 1 flag_c | |
129 | + | # echo "Flag -c has value '$flag_c'" | |
130 | + | # echo "Flag -c has value '$(arg c 1)'" | |
131 | + | ||
132 | + | # arg d 1 flag_d | |
133 | + | # echo "Flag -d has value '$flag_d'" | |
134 | + | # echo "Flag -d has value '$(arg d 1)'" | |
135 | + | ||
136 | + | # argl flag1 1 flag_1 | |
137 | + | # echo "Flag --flag1 has value '$flag_1'" | |
138 | + | # echo "Flag --flag1 has value '$(argl flag1 1)'" | |
139 | + | ||
140 | + | # argl flag2 1 flag_2 | |
141 | + | # echo "Flag --flag2 has value '$flag_2'" | |
142 | + | # echo "Flag --flag2 has value '$(argl flag2 1)'" | |
143 | + | ||
144 | + | # arg e 0 arg_e | |
145 | + | # echo "Arg -e has value '$arg_e'" | |
146 | + | # echo "Arg -e has value '$(arg e 0)'" | |
147 | + | ||
148 | + | # arg f 0 arg_f | |
149 | + | # echo "Arg -f has value '$arg_f'" | |
150 | + | # echo "Arg -f has value '$(arg f 0)'" | |
151 | + | ||
152 | + | # argl arg1 0 arg_1 | |
153 | + | # echo "Arg --arg1 has value '$arg_1'" | |
154 | + | # echo "Arg --arg1 has value '$(argl arg1 0)'" | |
155 | + | ||
156 | + | # argl arg2 0 arg_2 | |
157 | + | # echo "Arg --arg2 has value '$arg_2'" | |
158 | + | # echo "Arg --arg2 has value '$(argl arg2 0)'" |
上一页
下一页