2

I have a string like this, name it Options:

"printer-is-accepting-jobs=true printer-is-shared=false printer-location=Library printer-make-and-model='HP LaserJet 600 M601 M602 M603' printer-state=3"

they are "options=values" format, separated by spaces. but the "printer-make-and-model" has value with spaces.

tried command:

for word in $Options; do echo $word; done

all the HP LaserJet 600 M601 M602 M603 are splited.

How to deal with this in bash command?

3
  • perhaps one of the answers here will solve your problem stackoverflow.com/questions/9084257/…
    – clancer
    Commented Feb 28, 2014 at 4:21
  • 1
    Exactly, what do you want?
    – higuaro
    Commented Feb 28, 2014 at 4:41
  • @h3nr1x. I would like to split the string to arrays, option=value for each line.
    – TonyL2ca
    Commented Feb 28, 2014 at 4:58

4 Answers 4

2

Using grep -oP:

grep -oP "printer-make-and-model='\K[^']*" <<< "$s"
HP LaserJet 600 M601 M602 M603

OR using sed:

sed "s/^.*printer-make-and-model='\([^']*\).*/\1/" <<< "$s"
HP LaserJet 600 M601 M602 M603
3
  • Thank you! sorry, forget to mention, I'm on Mac. it doesn't have the -P options, what is the -P for?
    – TonyL2ca
    Commented Feb 28, 2014 at 4:40
  • I am also on OSX and grep -P is available (-P for PCRE)
    – anubhava
    Commented Feb 28, 2014 at 4:46
  • 1
    :) @jaypal you can take any regex/code from my answer. There is no copyright as I learnt most of it from SO and other forums.
    – anubhava
    Commented Feb 28, 2014 at 5:32
1

Anubhava's regex is good, so if you don't have grep -P option then you can try:

ack command:

$ ack -ho "printer-make-and-model='\K[^']*" <<< "$options"
HP LaserJet 600 M601 M602 M603

or Perl:

$ perl -nle "print $+{f} if /printer-make-and-model='(?'f'\K[^']*)/" <<< "$options"
HP LaserJet 600 M601 M602 M603
0
1

You can do this with multiple awk statements:

while read record; do
    while read key value; do
        echo "K=($key) V=($value)"
    done< <(awk -F"=" '{printf("%s %s\n", $1, $2)}' <<< $record)
done< <(awk -F"printer-" '{for(i=2;i<NF;i++){printf("printer-%s\n", $i)}}' <<< $string)

This will split to output into key value pairs.

1
  • @"Tim Verhoeven", amazing! yours' give me the whole list! Thank you!
    – TonyL2ca
    Commented Feb 28, 2014 at 23:12
0

Since you need to parse options, you can use getopt. However, this requires to use the evil eval command. So be careful about your input.

$ string="printer-is-accepting-jobs=true printer-is-shared=false printer-location=Library printer-make-and-model='HP LaserJet 600 M601 M602 M603' printer-state=3"
$ eval a=("$string")
$ eval b=($(getopt --long printer-make-and-model: -- ${a[@]/#/--} 2>/dev/null))
$ echo "${b[1]}"
HP LaserJet 600 M601 M602 M603
2
  • on my Mac, echo "${b[1]}" gets "printer-make-and-model:"
    – TonyL2ca
    Commented Feb 28, 2014 at 23:10
  • Frankly, I haven't tried it on mac, but I think, getopt on mac gives different output than on my system. try for x in "${b[@]}; do echo $x; done to see if the order of parameters has changed in the getopt output...
    – anishsane
    Commented Mar 3, 2014 at 5:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.