views:

115

answers:

2

I'm trying to remove a case clause from a bash script. The clause will vary, but will always have backslashes as part of the case-match string.

I was trying sed but could use awk or a perl one-liner within the bash script.

The target of the edit is straightforward, resembles:

 $cat t.sh
 case N in 
 a\.b); 
   #[..etc., varies] 
 ;;
 esac

I am running afoul of the variable expansion escaping backslashes, semicolons or both. If I 'eval' I strip my backslash escapes. If I don't, the semi-colons catch me up. So I tried subshell expansion within the sed. This fouls the interpreter as I've written it. More escaping the semi-colons doesn't seem to help.

X='a\.b' ; Y=';;'   
sed -i '/$(echo ${X} | sed -n 's/\\/\\\\/g')/,/$(echo ${Y} | sed -n s/\;/\\;/g')/d t.sh

And this:

perl -i.bak -ne 'print unless /${X}/ .. /{$Y}/' t.sh  # which empties t.sh

and

eval perl -i.bak -ne \'print unless /${X}/ .. /{$Y}/' t.sh  # which does nothing
A: 
X='a\.b'
Y=';;'
perl -i.bak -ne 'print unless /\Q'$X'/ .. /\Q'$Y'/' t.sh

This is playing games with shell quoting, but it works pretty well. :)

hobbs
Gracias! I'm curious as to how to bend bash to my will, but I'll take this and run!
ChrisSM
Changing my vote for solution. The Perl works, but the printf stays within bash.
ChrisSM
A: 

Bash's printf has a quoting feature that will help:

X='a\.b'; Y=';;'
sed "/$(printf "%q" "$X")/,/$(printf "%q" "$Y")/d" t.sh

or you can additionally use the printf variable assignment feature:

printf -v X "%q" 'a\.b'
printf -v Y "%q" ';;'
sed "/$X/,/$Y/d" t.sh

Note the use of double quotes around the sed command argument. Single quotes will prevent the expansion of variables and command substitution. When those aren't being used, though, it's usually best to use single quotes.

Dennis Williamson