Skip to content

Instantly share code, notes, and snippets.

@allex
Last active August 25, 2021 04:35
Show Gist options
  • Save allex/69e0673a54dd1c3fb786d272f719ad89 to your computer and use it in GitHub Desktop.
Save allex/69e0673a54dd1c3fb786d272f719ad89 to your computer and use it in GitHub Desktop.
#!/usr/bin/env awk -f
# Parse option args with an OPTSTRING
#
# Author: Allex Wang ([email protected])
# Last Modified: Tue Aug 24, 2021 20:08
#
# Usage: echo "<OPTS>|<ARGS>" | parse_args
# eg> echo "-c 10 --welcome 'hi allex' -f |-c:,-v,--welcome:" | awk -f parse_args.awk
#
# while read -r -d $'\0' k v; do
# case "$k" in
# grep) grep="$v" ;;
# __ARGV_REMAINS__) eval set -- "$v" ;;
# esac
# done < <(echo "$* |--grep:" | awk -f parse_args.awk)
#
# GistID: 69e0673a54dd1c3fb786d272f719ad89
# GistURL: https://gist.github.com/allex/69e0673a54dd1c3fb786d272f719ad89
function tokenize(s, start_idx, tokens) {
len = length(s);
i = 0;
sb = "";
c = "";
open = "";
n = start_idx - 1;
if (len < start_idx) {
return 0
}
while (n <= len) {
is_last = n == len
c = s[n++];
if (c == "'" || c == "\"") {
level++;
if (open == "") {
open = c;
} else if (open == c) {
open = "";
}
}
if (c == " " && open == "") {
tokens[++i] = sb;
sb = "";
continue;
}
sb = sprintf("%s%s", sb, c);
if (is_last) {
tokens[++i] = sb;
}
}
return i
}
function split_opts (s, tokens) {
split(s, arr, "");
return tokenize(arr, 1, tokens);
}
function error (msg) {
print msg > "/dev/stderr"
}
function debug (msg) {
print msg > "/dev/stderr"
}
BEGIN { FS="|"; EX_ERR=0; }
{
if (NF != 2) {
error("Usage: echo \"<OPTS>|<ARGS>\" | parse_args \neg> echo \"-c 10 --welcome 'hi allex' -f |-c:,-v,--welcome:\" | parse_args");
EX_ERR = 254;
exit;
}
gsub(/^[ \t]+|[ \t]+$/, "", $1);
gsub(/^[ \t]+|[ \t]+$/, "", $2);
opts_str = $2;
args_str = $1;
n = split(opts_str, a, /,/);
for (i = 1; i <= n; i++) {
if (match(a[i], /:$/) > 0) opt_tps[substr(a[i], 0, RSTART - 1)] = 1;
else opt_tps[a[i]] = 0;
}
n = split_opts(args_str, a);
j = 0;
for (i = 1; i <= n; i++) {
opt = a[i];
if (opt !~ /-+.*/ || opt_tps[opt] == "") {
remains[j++] = opt;
continue;
}
opt_t = opt_tps[opt];
if (opt_t == 0 && i < n && a[i + 1] !~ /-+.*/) {
error("error: invalid val for opt: " opt)
EX_ERR = 253;
exit 1;
}
sub(/^-+/, "", opt);
if (opt_t == 0) {
args[opt] = "TRUE";
} else {
args[opt] = a[++i];
}
}
for (k in args) printf "%s\n%s\0", k, args[k]
# append remains args
sb = ""
for (k in remains) {
printf k
sb = sprintf("%s %s", sb, remains[k]);
}
printf "%s\n%s\0", "__ARGV_REMAINS__", sb
}
END { exit EX_ERR }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment