0

I'm trying to extract the value of keys entered as options for a command-line bash script and failing.

I've tried matching regex with grep and sed both with and without the -E option. I can get a grep to work extracting keys from the initial command input:

grep -wo -- "-[^ ]*"

Works to extract keys from the command line that have "-" or "--" format, but I need the values between two keys or from a key to the end of line if there's no additional key(s).

key="-r"
input="command -r root1 root2 -s ip"

echo $input | sed "s/^.*$key \([^-]\+\)\( -.\+$\|$\)/$key has value \1/g;"

Output:

command -r root1 root2 -s ip

Expected output:

root1 root2

Clearly, \1 is matching the whole line, but I just need the contents of the input line from the $key to the next key or the end of line. Any assistance would be appreciated.

  • Do you specifically want to get values for the option `-r`? – anishsane Jul 31 '19 at 15:06
  • In this example, yes. There are a number of switches for the script. I have a variable for the switches `$(echo "$*" | grep -wo -- "-[^ ]*" )` and then loop through the switches, parse them with a case statement, and then perform a few different commands based on the values of the switches. Switches have values like -a or --assign and each switch can have one or more values based on whether the input is an option or a list of devices. A few examples of command-line input would be: `command.sh device1 device2`, `command.sh device1 -s ip`, `command.sh --root CompanyDevice --first 35 --last 99"` – phonedog365 Jul 31 '19 at 15:11
  • So, is `"$input"` received as a single string, or are you creating it by concatenating all the arguments? – anishsane Jul 31 '19 at 15:13
  • 1
    Also, I would suggest checking the `getopts` built-in feature of bash. (Just run `help getopts` on `bash` terminal.) – anishsane Jul 31 '19 at 15:14
  • For this example I just put a sample command-line entry into `$input`, but yeah `$input` is essentially `$*`. – phonedog365 Jul 31 '19 at 15:16
  • 1
    Possible duplicate of [How to use sed/grep to extract text between two words?](https://stackoverflow.com/q/13242469/793796). – anishsane Jul 31 '19 at 15:16
  • 1
    If you are getting separate `$1`, `$2` and then using `input="$*"`, then it is wrong approach. Just looping through `"$@"` is better option. loop manually with `for`, or with `getopts`. Google for [`getopts` examples](https://www.google.com/search?q=getopts+examples). There should be plenty of them. Note that `getopts` and [`getopt`](https://mariusvw.com/2013/02/24/bash-getopt-versus-getopts/) are different. `getopts` is simpler and built-in into bash. – anishsane Jul 31 '19 at 15:18
  • `getopts` was an original consideration, but users can also pipe in device names or IPs to have them processed by the command. Or they can use the options to create build lists based on input. I like the simplicity of `getopts` but it wasn't going to be the right tool for the job. – phonedog365 Jul 31 '19 at 17:26

2 Answers2

1

Figured it out with some examples from the "possible duplicate" comment.

key="-a";
input="command -a option1 option2 -r root1 root2 -s ip ip ip";
echo $input | sed -E "s/^.*$key ([^-]*)(-.*$|$)/\1/g;"

produces the desired "option1 option 2" output. I think sed wasn't liking my \(..\|..\) clause. Switched to sed -E and removed the backslashes and it's working.

Thanks for the assist.

0

This might work for you (GNU sed):

key='-r'
sed -En 's/ -\w */\n&/g;s/.*\n '$key' *([^\n]*).*/\1/p' file

Prefix each option by a newline and then extract the required option up and until the next newline.

potong
  • 55,640
  • 6
  • 51
  • 83