LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This 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


Reply
  Search this Thread
Old 04-20-2023, 01:39 PM   #1
Faki
Member
 
Registered: Oct 2021
Posts: 574

Rep: Reputation: Disabled
Simplification of conditional patterns


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

Last edited by Faki; 04-20-2023 at 07:01 PM.
 
Old 04-20-2023, 09:08 PM   #2
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,679
Blog Entries: 4

Rep: Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947
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.
 
Old 04-21-2023, 01:22 AM   #3
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,337
Blog Entries: 3

Rep: Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732Reputation: 3732
Quote:
Originally Posted by sundialsvcs View Post
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
 
Old 04-21-2023, 01:37 AM   #4
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,992

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
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....)
 
Old 04-21-2023, 02:45 AM   #5
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,818

Rep: Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211
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.
 
Old 04-22-2023, 12:40 PM   #6
Faki
Member
 
Registered: Oct 2021
Posts: 574

Original Poster
Rep: Reputation: Disabled
The loop is needed because the contents of the pary is arbitrary rather than hardwired. The array denotes the set of possible user input formats.

For instance

Code:
pary=( "-p+([[:digit:]])"  "-g+([[:digit:]])"  "-q" )
I then want to match these with the actual user inputs (stored in arg)

Code:
  for gpn in "${pary[@]}"
  do
    if [[ "$arg" == $gpn ]]; then
What I do after is dependent on whether the user used the digit form (e.g "-p+([[:digit:]])") or the isolated predicate form (e.g. "-q").

How can I handle the aforementioned functionality in a clear and compact way?

Last edited by Faki; 04-23-2023 at 02:23 AM.
 
Old 04-22-2023, 02:28 PM   #7
Faki
Member
 
Registered: Oct 2021
Posts: 574

Original Poster
Rep: Reputation: Disabled
...

Last edited by Faki; 04-22-2023 at 11:37 PM.
 
Old 04-23-2023, 03:36 AM   #8
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,992

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
Quote:
Originally Posted by Faki View Post

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.
 
  


Reply

Tags
bash



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Search multiple patterns & print matching patterns instead of whole line Trd300 Linux - Newbie 29 03-05-2012 07:41 PM
LXer: Linux leaders call for open source license simplification LXer Syndicated Linux News 0 10-30-2006 08:54 PM
LXer: Open source in '05 -- simplification, assurance LXer Syndicated Linux News 0 12-18-2005 10:31 AM
unix scrpit simplification kirmet Programming 2 10-05-2005 05:53 AM
Remembering patterns and printing only those patterns using sed bernie82 Programming 5 05-26-2005 05:18 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 11:34 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration