2

I am trying to find a way to find all string between two patterns. This is easy:

    cat file | sed -n "/pattern_start/,/pattern_end/p"

However, in this case I want to use a variable inside the sed script, which also is fine:

    cat file | sed -n "/$var1/,/pattern_end/p"

However, if the variable contains special escape characters such as, '/' this does not work. Then I read that one could replace the escape character to anything, such as # or |

For example, lets say:

    var1=/some/funny/path
    cat file | sed -n "#$var1#,#pattern_end#p"

But this does not work for me. What am I doing wrong? I have tried to find the answer on Google etc but without success and I cant really find any other question here on Stackoverflow which deals with this exact problem.

Euklides
  • 564
  • 1
  • 10
  • 35
  • 2
    don't use `cat` command for this. – Avinash Raj May 21 '14 at 11:44
  • What's the value for `var1` variable? Please show your file for us. – Avinash Raj May 21 '14 at 11:45
  • possible duplicate of [How to escape a previously unknown string in regular expression?](http://stackoverflow.com/questions/5328995/how-to-escape-a-previously-unknown-string-in-regular-expression) – hek2mgl May 21 '14 at 11:51
  • I made an edit to the question so it will be more clear what var1 looks like. – Euklides May 21 '14 at 11:52
  • @hek2mgl The solution in that answer has limitations. – ceving May 21 '14 at 11:55
  • 1
    See here: http://stackoverflow.com/questions/4133286/sed-or-similar-dont-interpret-as-regex-interpret-as-fixed-string-literal or here: http://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern – ceving May 21 '14 at 11:56
  • 1
    I do not want to replace something. That is what all examples shows, but not how to deal with this problem I explained. – Euklides May 21 '14 at 11:59
  • @ceving The post you linked is about replacement. This one is not about replacement. – hek2mgl May 21 '14 at 11:59
  • @hek2mgl it does not matter if you use the regular expression in a replacement or a search. – ceving May 21 '14 at 12:01

2 Answers2

3

You could do this:

sed -n "/$(sed 's#/#\\/#g' <<< "$var1")/,/end/p" file

You'll have to protect the contents of your variable from whatever delimiters you choose.


To address hek2mgl's concern, we could escape all potentially troublesome characters:

re_escape() {
    sed 's#[^[:alnum:]_]#\\&#g' <<< "$*"
}
sed -n "/$(re_escape "$var1")/,/end/p" file
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • (this is what I would had suggested too but) what if `$var1` contains something like `\(` or other characters which may be interpreted by sed , except of the delimiter? (off-topic) In PHP there is a function called `preg_quote()` which can be used for this. Would be nice to have something like this. I guess a bash function can help (if well prepared) – hek2mgl May 21 '14 at 12:02
  • 2
    I predict the same comment could be made for every solution to this question. – glenn jackman May 21 '14 at 12:30
  • And for further readers, perl has the `quotemeta` function for this purpose; ruby has `Regexp.escape`; python, `re.escape` -- I think all of these merely escape all non-word characters. – glenn jackman May 21 '14 at 12:39
  • @hek2mgl, here's a bash function for you. – glenn jackman May 21 '14 at 12:46
  • Looks good! `[^[:alnum]_]` should work in most or even all(?) cases. Much simpler than what I had in mind. Btw, "my" sed (GNU-sed-Version 4.2.1 ) interpretes `_` as `alnum`. Is this not safe for other versions of sed? – hek2mgl May 21 '14 at 12:54
  • Are you sure? I have the same version and this outputs nothing: `echo "---_---" | sed -n '/[[:alnum:]]/p'` – glenn jackman May 21 '14 at 16:11
2

To change the delimiter, you need to escape the first one, i.e. something like, \!FIND!. Also, it is best to use single quotes, leave them when needed and use double quotes for variable interpolation. Then your command looks like this:

sed -n '\!'"$var1"'!,\!'"$var2"'!p' inpu
perreal
  • 94,503
  • 21
  • 155
  • 181