[SOLVED] Passing variables which contain special characters to sed
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
The problem is, this list will vary each time I run the loop. The actual list I'm using contains upwards of 150 items, and the number of items containing special characters varies. I need a way to escape special characters no matter what is passed to the variable.
Will it always be preceded by "text"? If so escaping the character after "text" might work - \B would likely still see the character as B and \/C would make it see it as /C.
In Bash, to escape characters special to standard sed patterns, you could try something like the following within the loop:
Code:
# start with the original pattern
escaped="$i"
# escape all backslashes first
escaped="${escaped//\\/\\\\}"
# escape slashes
escaped="${escaped//\//\\/}"
# escape asterisks
escaped="${escaped//\*/\\*}"
# escape full stops
escaped="${escaped//./\\.}"
# escape [ and ]
escaped="${escaped//\[/\\[}"
escaped="${escaped//\[/\\]}"
# escape ^ and $
escaped="${escaped//^/\\^}"
escaped="${escaped//\$/\\\$}"
# remove newlines
escaped="${escaped//[$'\n']/}"
# Now, "$escape" should be safe as part of a normal sed pattern.
# Note that it is NOT safe if the -r option is used.
Note that since sed cannot match a newline as part of a pattern, I chose above to just remove any newlines altogether; you could just as well replace them with spaces or any other character or string. Any newlines in a pattern will cause the sed to fail with an error message.
The easiest way is simply to change the delimiter that sed uses.
(Edit: the easiest way to avoid conflicting with the delimiter at least. For regex characters, you'd have to do variable sanitizing as above.)
For the 's' substitution command, just replace the slash with another ascii character. Simply choose something that won't ever be found in the expression itself.
You can do the same thing for the target range brackets, except that the first instance needs to be prefixed with a backslash.
To use the underscore as the delimiter, for example (spaced out a bit for better readability):
Code:
for i in "textA" "textB" "text/C"; do
sed -n "\_$i_ , \_^$\|pattern_ p" targetfile
done
You can even use non-printing characters, provided you can enter them into the shell. The ansi-c style ($'..') quoting mechanism makes this fairly simple. The only characters in the ascii table that can't be used are null and newline. It's probably easier to store the delimiter in a variable first.
Code:
D=$'\e' #The sed delimiter will be the ascii escape character
for i in "textA" "textB" "text/C"; do
sed -n "\\${D}$i${D} , \\${D}^$\|pattern${D} p" targetfile
done
(Edit: gotta escape the backslash in front of the "$"s too, when used in double-quotes)
Last edited by David the H.; 06-21-2012 at 11:27 AM.
I was trying to change the delimiter previously, but I didn't have the syntax correct, so I was getting an error. When I use : as the delimiter in the format you listed above, it's working!
Thanks to everyone else who offered input as well!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.