1

I have a line with a comment. I use parameter substitution to condition the line into a variable "source". A test statement shows that the value of source is "Simple:", but the case statement can't match it. If I use command substitution to "source=$(echo $source)", test says it matches, like before, and the case statement works now. Am I missing something fundamental, should I not use parameter substitution to do this, or is this weird? Bash version: GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu). Thanks for taking a look.

Piping the line to sed with echo works as expected. If no parameter substitution is performed on a variable, case works as expected. Example: line="Simple:" and case $line in ... no issues.

#!/bin/bash

line="Simple: #comment and space to be removed"
source=${line//#*}
source=${source//^[[:space:]]*}
source=${source//*[[:space:]]$}

[[ $source =~ 'Simple:' ]] && echo -e "\n1st test match" || echo -e "\nno 1st test match"

case $source in
    'Simple:')  
        ops="Simple"
        echo -e "\n1st try case match.  Ops is $ops"
    ;;
    *)
        echo -e "\nno natch in 1st case"
    ;;
esac

source=$(echo $source)

[[ $source =~ 'Simple:' ]] && echo -e "\n2nd test match" || echo -e "\nno 2nd test match"

case $source in
    'Simple:')  
        ops="Simple"
        echo -e "\n2nd try case match.  Ops is $ops"
    ;;
    *)
        echo -e "\nno match 2nd case"
    ;;
esac

I expect "Simple:" would match in the first case statement, but it doesn't until I run "source=$(echo $source)".

1 Answers1

1

Quoting from man bash:

${parameter/pattern/string}

Pattern substitution. The pattern is expanded to produce a pattern just as in pathname expansion, Parameter is expanded and the longest match of pattern against its value is replaced with string. ...

That means, these lines:

source=${source//^[[:space:]]*}
source=${source//*[[:space:]]$}

do nothing at all, ^ and $ doesn't work in pathname expansion; the pattern is not a regex. source=$(echo $source) makes it work because since $source is not in double-quotes, its value undergoes word splitting and the space at the end gets lost.

The proper way of doing this using parameter expansions is:

source=${line%%#*}
source=${source#${source%%[^[:space:]]*}}
source=${source%${source##*[^[:space:]]}}
oguz ismail
  • 1
  • 16
  • 47
  • 69
  • 1
    Also, the reason `[[ $source =~ 'Simple:' ]]` was matching is that it does a *substring* search (because it isn't anchored). Actually, using `=~` here is weird, since it does regex matching, but then single-quoting the pattern string suppresses all regex syntax making it just a string (substring) match. Use the `=` test for plain equality. – Gordon Davisson Sep 03 '19 at 05:24
  • 1
    I was definitely missing something fundamental, but this is pointing in the right direction. I ran the above lines in a script with line: " Simple Simple: #Comment" to test, and the results were exactly what I was trying to achieve. 1st line removed comments, 2nd line removed preceding spaces, and 3rd removed spaces from the end. The space between "Simple Simple:" was preserved. Thank you for the links in the answer too. "Simple: #comment" ran through the test and case statements exactly as expected with your corrections. – SirSimonMilligan Sep 04 '19 at 23:27