0

I'm fairly new to Bash so please forgive me, but I'm building a Bash script that can accept a user input command that can have a lot of switches. I need to write a function that pulls specific data from that user provided command.

I can't seem to find a way to pull each word after "-mode" and push it into an array or list of some sort.

Here is an example of what the user input command might look like:

/home/custom/function/that/accepts/a/billion/switches  random_info random_info2 -worker vendor_schmo  -switch_one  -anotherOne  -more_switches  -optionTwo        -mode FOO -mode BAR -mode BAZ -mode BAG -mode DAT -mode RAR

I've tried fiddling with awk -F "-mode" '{ print $1 }' and that didn't work. Any advice would be much appreciated!!

Here is the snippet from the script that pulls this info:

manualRunMain(){
  local command
  manualRunHeaderPrint
  echo
  echo
  echo
  echo
  lineBreakPrint
  read -p "Enter your command here: " command
  sleep .25
  manualRun "$command"
}

manualRun(){
  manualRunHeaderPrint
  jobRunSubHeaderPrint
  pullModeNames "$1"
}

pullModeNames(){

}
4
  • Welcome to stack overflow, could you please add sample expected output in code tags too? Commented Aug 14, 2017 at 18:15
  • I don't think I need anything output, I just need to push each word after each "-mode" into an array. I think that would be enough and I could take it from there. Commented Aug 14, 2017 at 18:20
  • In general, you should consider following the practices given in BashFAQ #35 for your given purpose. The list of arguments your command is given is not passed as a string -- rather, it's passed as an array of strings -- and treating it as if a string means you adopt a bunch of bugs (for instance, you lose the ability to distinguish between -foo "bar baz" and -foo bar baz). Commented Aug 14, 2017 at 19:16
  • (and if you have a string and need to split it into a list of strings in a way that's comparable to what the shell would do, such that that array can then be parsed through using standard tools, that's a fairly involved question in its own right, with an answer that's much more complicated than array=( $string ); that said, it is a question with accepted, canonical answers already present in our knowledge base). Commented Aug 14, 2017 at 19:47

2 Answers 2

2

You can use RS variable in awk to tell to split data into separate records when it get -mode:

s='/home/custom/function/that/accepts/a/billion/switches  random_info random_info2 -worker vendor_schmo  -switch_one  -anotherOne  -more_switches  -optionTwo        -mode FOO -mode BAR -mode BAZ -mode BAG -mode DAT -mode RAR'

printf '%s' "$s" | awk -v RS="-mode[[:space:]]*" 'NR>1'
FOO
BAR
BAZ
BAG
DAT
RAR

To populate an array:

mapfile -t arr < <(printf '%s' "$s" | awk -v RS="-mode[[:space:]]*" 'NR>1')

# examine array content
declare -p arr
declare -a arr=([0]="FOO" [1]="BAR" [2]="BAZ" [3]="BAG" [4]="DAT" [5]="RAR")
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks! This is perfect. I'd upvote you but I don't have reputation to do it yet :)
Notice that the command to populate an array is subject to word splitting and glob expansion, so if you have an argument -mode 'has space', it will break. Instead, you could use mapfile: mapfile -t arr < <(awk -v RS="-mode" 'NR>1{ print $1 }' <<< "$s")
@BenjaminW.: Very good point, however if there is any whitespace then even print $1 will print only first part.
Since you're using RS, can't you print $0 in the first place? Might have to adjust RS to swallow whitespace. Something like RS="-mode *".
BTW, I agree that this is the best answer to the question asked in the title, but the intended use case given in the question text (command-line parsing) gives me qualms about this answer's fitness to purpose.
|
0

I just came up with basically the same answer as @anubhava but with GNU grep instead of awk:

$ cmd="... -more_switches  -mode FOO BAR -mode BAZ -mode BAG -mode CAT DAT HAT -mode RAR"
$ mapfile -t modes < <(grep -oP -- '-mode \K.+?(?= -mode|$)' <<<"$cmd")
$ printf "%s\n" "${modes[@]}"
FOO BAR
BAZ
BAG
CAT DAT HAT
RAR

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.