Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I am parsing short options that involve either the option-value stuck together (e.g. -pVAL, -qVAL). I construct the two possible options in array pary, loop through them, storing the value in _vl.
I do think I can simplify the code
Code:
pary=("-p+([[:digit:]])" "-q+([[:digit:]]))
for gpn in "${pary[@]}" # Loop through possible short options
do
if [[ "$arg1" == $gpn ]]; then
if [[ "$arg1" =~ ^[-][[:alpha:]][[:digit:]]+$ ]]; then
if [["${arg1:2}" =~ ^[[:digit:]]+$ ]]; then
_vl="${arg1:2}" ; _sf=1 ; break
else
_vl="" ; _sf=1
printf '%s\n' "${arg1} Value failed numeric validation"
fi
fi
break
fi
done
with the following
Code:
pary=("-p+([[:digit:]])" "-q+([[:digit:]]))
for gpn in "${pary[@]}" # Loop through possible short options
do
if [[ "$arg1" == $gpn ]]; then
if [[ "$arg1" =~ ^[-][[:alpha:]][[:digit:]]+$ ]]; then
_vl="${arg1:2}" ; _sf=1 ; break
else
_vl="" ; _sf=1
printf '%s\n' "${arg1} Value failed numeric validation"
fi
break
fi
done
I can very-simply say that "I would never want to encounter your [incomprehensible ... although it obviously works ...] code" as your predecessor, after you had moved on to your next job. The very-primitive programming capabilities of the "bash" shell were, IMHO, never intended to be used for "real work."
It is for this very reason that the #!"shebang!" construct was invented. If you, for example, put #!/usr/bin/php as the very first line, then you can write the remainder of the script in PHP. The shell will silently transfer the remainder of the script to the specified language interpreter for processing, and the end-user will be none the wiser.
Last edited by sundialsvcs; 04-20-2023 at 09:09 PM.
I can very-simply say that "I would never want to encounter your [incomprehensible ... although it obviously works ...] code" as your predecessor, after you had moved on to your next job. The very-primitive programming capabilities of the "bash" shell were, IMHO, never intended to be used for "real work."
+1
It is time to switch to a different parser. Code is read many more times than it is written or modified and thus the return on investment for having readable code is very high. Conversely for the same reasons having code which is hard to understand has a very high cost which gets extracted repeatedly. Therefore priority needs to be on ease of reading for whoever comes next, even if it is just your future self.
Good old Perl remains ubiquitous and has been the go-to for scripting for decades, especially where string processing is involved. It was famous as the 'glue which holds the Internet together' and while it still has that role it is less famous. Python is another option.
(Edit: Getopt::Long is one relevant CPAN module)
I tend to use plain POSIX shell when possible, very rarely use Bashisms, and often use AWK when it suits the task. However, I mostly escalate directly to Perl when the shell scripting would get complex and the task is not suited to AWK.
tldr; choose the right tool for the job
Last edited by Turbocapitalist; 04-21-2023 at 01:27 AM.
Reason: Getopt::Long
additionally to post #2 and #3 [I can only repeat myself] why do you ask us if that code works for you?
Error messages should be sent to stderr, not stdout.
Incorrect command line arguments should stop the script execution. Also usually in such cases the usage is printed (just to know what went wrong and what would be the correct way....)
Yes, you can delete that if clause; it is redundant.
And it is even a bug fix: now the else branch can run.
Looks still a bit too complicated.
You use extended glob pattern and then ERE pattern...
Perhaps something like this (only extended globs, no loop)
Code:
eglobd="+([[:digit:]])"
if [[ $arg1 == -[pq]* ]]
then
if [[ "$arg1" == ??$eglobd ]]
then
_vl="${arg1:2}"
else
_vl="" ; _sf=1
printf '%s\n' "${arg1} Value failed numeric validation"
fi
fi
or this variant (case-esac with logical OR)
Code:
eglobd="+([[:digit:]])"
case $arg1 in
( -p* | -q* )
if [[ "$arg1" == ??$eglobd ]]
then
_vl="${arg1#??}"
else
_vl="" ; _sf=1
printf '%s\n' "${arg1} Value failed numeric validation"
fi
;;
esac
Last edited by MadeInGermany; 04-21-2023 at 03:35 AM.
How can I handle the aforementioned functionality in a clear and compact way?
I would say there is no simple way.
As far as I see dynamic parameter/argument specification is available for example in python, but I don't think you want to reimplement it in bash.
The way you can do it is to have a structure (which does not exist in bash). This will contain the regex to match the option, the parsing mechanism to "calculate" the value of that option, some kind of validation and also the variable which will store the result.
As far as I see your best possibility is to rewrite getopt (in c) to handle all the requirements you have.
By the way, you still need to validate those dynamic specifications, your bash script will crash in case of an incorrect regex.
I still don't know that specification, if you want to handle long options and short options, if you allow arguments without option, if you allow required and optional arguments, if some options have default values, if you allow multiple arguments for one option, if short options can be combined into one string, if the order of the arguments is important, if they can be repeated. Not to speak about the case when you want to generate a usage page.
The way is to go thru the arguments (one by one) - this is a simple while loop, try to identify them (this can be tricky, especially if you allow partial match for long options [--my_arg is accepted instead of --my_argument] and validate, process accordingly. I would try to split the input string into parts, like - or --, option name, value and do the processing based on that name.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.