1

I have this string:

str='1 2 3 var="foo bar" 4 5 6'

Also it could be like this:

str="1 2 3 var='foo bar' 4 5 6"

How would I replace spaces with + only inside quotes(double or single)?

The result should be like:

1 2 3 var="foo+bar" 4 5 6

or

1 2 3 var='foo+bar' 4 5 6

In case the var is single quoted.

var can be anything, it is not strong match. Also it could be missing at all, like this:

str='1 2 3 "foo bar" 4 5 6'

I don't want to use awk, sed, or perl to do this.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Bill Parker
  • 135
  • 1
  • 8
  • see my answer here - http://stackoverflow.com/questions/12821302/split-a-string-only-by-spaces-that-are-outside-quotes - it does exactly what you asking –  Oct 10 '12 at 21:27

3 Answers3

3

Loop over the string character by character. Keep a flag telling whether you are inside quotes or not. Based on the flag, replace spaces if needed:

#! /bin/bash
str='1 2 3 var="foo bar" 4 5 6'

result=''
inside=0
for (( i=0 ; i<${#str} ; i++ )) ; do
    char=${str:i:1}
    if [[ $char == [\"\'] ]] ; then
        let inside=!inside
    fi
    (( inside )) && char=${char/ /+}
    result+=$char
done
echo $result
choroba
  • 231,213
  • 25
  • 204
  • 289
0
$ echo $str | awk -F= '{sub(/ /,"+",$2);}1' OFS="="
1 2 3 var='foo+bar' 4 5 6

Using awk, replace the space with + only in the second field(2nd field happens to be the expression when delimited by =).

choroba
  • 231,213
  • 25
  • 204
  • 289
Guru
  • 16,456
  • 2
  • 33
  • 46
0

This is identical to choroba's answer, just using a different technique to iterate over the string:

#!/bin/bash

str='1 2 3 var="foo bar" 4 5 6'
result=''
declare -i inside=0
while IFS= read -n1 char; do
    [[ $char = [\"\'] ]] && inside=!inside
    (( inside )) && char=${char/ /+}
    result+=$char
done <<< "$str"
echo "$result"
chepner
  • 497,756
  • 71
  • 530
  • 681