Skip to content

Written in pure Bash (versions 4+) for scripts that accept arguments

License

Notifications You must be signed in to change notification settings

bash-utilities/argument-parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bash Argument Parser

This repository is intended as a git submodule for other Bash scripts that'd be fancier if they'd parse arguments.


Table of Contents


Requirements

Bash version 4.4 or greater and the following command line utilities;

  • printf for returning values between functions

  • sed for scrubbing values within select functions

  • declare with -a and -g options available for declaring globally scoped Bash variables and arrays

  • local with -n option available for passing references to variables between functions

See info printf and info sed for documentation and help declare and help local for more information on additional options.

Quick Start

Bash Variables

_module_https_url='https://github.com/bash-utilities/argument-parser.git'
_module_relative_path='modules/argument-parser'

Bash Submodule Commands

cd "<your-git-project-path>"

mkdir -vp "modules"

git submodule add -b master --name argument-parser "${_module_https_url}" "${_module_relative_path}"

Your ReadMe File

Your Quick Start Section

Clone with the following to avoid incomplete downloads



    git clone --recurse-submodules <url-for-your-project>


Update/upgrade submodules via


    git submodule update --init --recursive
    git submodule update --merge

Utilize Argument Parser

#!/usr/bin/env bash


## Find true directory this script resides in
__SOURCE__="${BASH_SOURCE[0]}"
while [[ -h "${__SOURCE__}" ]]; do
    __SOURCE__="$(find "${__SOURCE__}" -type l -ls | sed -n 's@^.* -> \(.*\)@\1@p')"
done
__DIR__="$(cd -P "$(dirname "${__SOURCE__}")" && pwd)"


## Source module code within this script
source "${__DIR__}/modules/argument-parser/argument-parser.sh"


## Save passed arguments and acceptable arguments to Bash arrays
_passed_args=("${@:?No arguments provided}")
_acceptable_args=(
    '--help|-h:bool'
    '--directory-path|-d:path'
    '--file-name:print-nil'
)

## Pass arrays by reference/name to the `argument_parser` function
argument_parser '_passed_args' '_acceptable_args'
_exit_status="$?"


## Print documentation for the script and exit, or allow further execution
if ((_help)) || ((_exit_status)); then
    cat <<EOF
Augments script responds to

--help | -h

    Prints this message and exits

--directory-path

    Example augment for paths such as ${_directory_path:-/tmp}

<file-name>

    Example argument that may print ${_file_name:-a file name}
EOF
    exit "${_exit_status:-0}"
fi


## Do scripted things with passed arguments, however, remember to check if
##  required values are not set and either throw an error or set a default
printf '_directory_path -> %s\n' "${_directory_path:?--directory-path not provided}"
printf '_file_name  -> %s\n' "${_file_name:-output.log}"

Arguments such as --file-name are transmuted into variable names like _file_name, and short options may be listed with pipes (|) as a separator; eg. --directory-path|-d|--dpath would match and set the _directory_path variable for -d, or --dpath, etc. The first option listed will become the variable name, thus it's a good idea to list the long option first, eg. -d|--directory-path would be a bad idea as that would set a variable named _d... a nightmare to debug.

Available argument parsing types are

  • :bool sets 0 or 1 for false or true if related argument was passed

  • :raw sets unfiltered value for related argument

  • :path sets value for related argument minus non-alphanumeric or; , ~, +, _, ., @, :, -, characters as well as removing duplicated .. and/or -- from the beginning of passed value

  • :posix filters passed value for non-alphanumeric or; _, ., -, characters as well as removing duplicated .. and/or -- from the beginning of passed value. Additionally the _, ., - characters are scrubbed from both the beginning and end of passed value, and only the first 32 characters that pass these constraints are set

  • :print sets passed value minus any non-[:print:]-able characters

  • :regex similar to :print, but also allows for tabs (\t) at the beginning and new lines (\n) at the end of the passed value

  • :list scrubs leading duplicated .. and/or -- from passed value and sets anything alphanumeric and; ,, +, _, ., @, :, - characters if any from passed value

  • :alpha_numeric scrubs any non-alphanumeric characters from passed value

Note, :list does not set an array but instead a string that contains the most common list separators, in the future an :array type might be added to set a Bash arrays too.

These are intended for catching or forgiving typos, and should not be considered secure in untrusted and/or hostile environments.

The -nil modifier may be appended to any but :bool option types to make an argument greedy, eg. --file-name from the above example script will also set from something like script-name.sh --directory-path=/tmp file-name.ext meaning that the --file-name option was assumed to prefix the file-name.ext value.

One warning regarding the -nil modifier, place argument options using -nil at the end/bottom of the _acceptable_args Bash array, eg...

_acceptable_args=(
    '--help|-h:bool'
    '--file-name|-f:print-nil'
    '--directory-path|-d:path'
)

... would be lead to a bad time when attempting to use the values within _file_name and _directory_path variables.

Multiple -nil modified options maybe stacked, eg...

_acceptable_args=(
    '--help|-h:bool'
    '--source-path|-s:path-nil'
    '--destination-path|-d:path-nil'
)

Commit and Push

git add .gitmodules
git add modules/argument-parser


## Add any changed files too


git commit -F- <<'EOF'
Submodule `bash-utilities/argument-parser` added for argument parsing


## Add anything else of note...
EOF


git push origin gh-pages

Notes

If upgrading from v0.0.2 to v0.0.3 then scrubber functions have been renamed! Eg. arg_scrubber_regex is now argument_parser__scrub__regex to avoid clobbering functions that maybe sourced within scripts making use of this project. This should not effect those only utilizing the argument_parser function.


License

Argument Parser documentation from Bash Utilities
Copyright (C) 2020  S0AndS0

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation; version 3 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.