1

This is an extension of my previous question. In that question, I needed to retrieve the text between parentheses where all the text was on a single line. Now I have this case:

(aop)
(abc
d)

This time, the open parenthesis can be on one line and the close parenthesis on another line, so:

(abc
d)

also counts as text between the delimiters '( )' and I need to print it as

abc
d

EDIT: In response to possible confusions of my question, let me clarify a little. Basically, I need to print text between delimiters which could span multiple lines.

for example I have this text in my file:

randomtext(1234
567) randomtext
randomtext(abc)randomtext

Now I want Sed to pick out text between the delimiter "(" and ")". So the output would be:

1234
567
abc

Notice that the left and right brackets are not on the same line but they still count as a delimiter for 1234 567, so I need to print that part of the text. (note, I only want the text between the first pair of delimiters).

Any help would be appreciated.

Community
  • 1
  • 1
Mark
  • 8,408
  • 15
  • 57
  • 81
  • 1
    I can hardly understand your question. – Vijay May 12 '11 at 05:48
  • @Rahul basically I need to do multi-line printing with Sed to print text between delimiters. – Mark May 12 '11 at 16:57
  • I have edited the question for better clarity. – Mark May 12 '11 at 17:06
  • @Jonathan thanks for the edit! Edit: Also, how did you get the text to appear on a gray background? – Mark May 12 '11 at 18:33
  • NP - though I see I should have changed 'for example' to 'For example'...You get 'code' to look like code by typing it in and then selecting it, and pressing the '{}' icon above the text editing box; that indents it four spaces, which indicates code, and uses constant-width font, and a gray background. It also stops the text wrapping. There's a link button too - you highlight the text (eg 'question') and click; then you can type (or, more usually, paste) the URL. – Jonathan Leffler May 12 '11 at 18:43

3 Answers3

4

Ah! another tricky sed puzzle :)

I believe this code will work for your problem:

sed -n '/(/,/)/{:a; $!N; /)/!{$!ba}; s/.*(\([^)]*\)).*/\1/p}' file

OUTPUT

For the provided input it produced:

1234
567
abc

Explanation:

  • -n suppresses the regular sed output
  • /(/,/)/ is for range selection between ( and )
  • :a is for marking a label a
  • $!N means append the next line of input into the current pattern space
  • /)/! means do some actions if ) is not matched in current pattern space
  • /)/!${!ba} means go to label a if ) is not matched in current pattern space
  • s/.*(\([^)]*\)).*/\1/ means replace content between ( and ) by just the content thus stripping out parenthesis
  • \1 is for back reference of group 1 i.e. text between \( and \)
  • p is for printing the replaced content
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 3
    I bow before your sed mastery. Your sed-fu is strong! – Steve Baker May 12 '11 at 20:01
  • @anubhava Thanks for the great answer and explanation! However, I am having trouble running this on slackware 13.37. The output is: sed: -e expression #1, char 22: unknown command: `$' – Mark May 12 '11 at 20:15
  • @mark: can you try this one: `sed -n '/(/,/)/{$!N; /)/!{$!N;}; s/.*(\([^)]*\)).*/\1/p;}' file` I don't have access to slackware but tested it on Mac & Linux. – anubhava May 12 '11 at 22:28
  • @anubhava I have tried the both code again and I am getting N: event not found. Could it be I am using a different standard of SED? (note I have tried it on both slackware and ubuntu.) – Mark May 16 '11 at 20:15
  • on Ubuntu is should be fine if it is current version of Ubuntu. In fact I built above command on my Ubuntu itself :) – anubhava May 16 '11 at 20:19
  • I am using ubuntu 9.10. The output is still linux006:~> sed -n '/(/,/)/{:a; $!N; /)/!{$!ba}; s/.*(\([^)]*\)).*/\1/p}' input1.txt N: Event not found – Mark May 16 '11 at 20:29
  • Meanwhile can you pls try this command: `sed -n '/(/,/)/{:a;$!N;/)/!{$!ba;};s/.*(\([^)]*\)).*/\1/p;}' file` (removed extra space) – anubhava May 16 '11 at 20:36
  • Yeah I have just tried it, it still seems to be giving me the same output. :( sorry to bother you so much. – Mark May 16 '11 at 20:39
  • @anubhava I have just install a brand new up to date version of linux and the code is working fine now but there is one minor problem, I have updated the sample input and output in the question I would like to tweak it to fit the case. – Mark May 16 '11 at 20:56
  • Glad that at least existing answer worked for you for your original problem. But your updated problem seems to be lot more different that the original one. I would suggest posting that update section as a new question pointing this one as reference. Since this being the old problem wouldn't get many people's attention. I will also have to think from fresh point how to solve the new problem now :) – anubhava May 16 '11 at 21:13
  • Thanks I have posted the new question. – Mark May 16 '11 at 21:24
0

The answer given didn't work for my case. What worked for me was:

cat file | tr -d '\n'

^^^ this puts the whole file in a single line by deleting line breaks.

and then I further piped it into the answer here. (note: instead of brackets, OPEN and CLOSE are used in that question)

cablewelo2ma
  • 139
  • 2
  • 7
0

This link has the answer. I am paraphrasing to match your need:

sed -n '1h;1!H;${;g;s/.*(\([^)]*\)).*/\1/;p}' < your_input
Chen Levy
  • 15,438
  • 17
  • 74
  • 92
  • it seems to work, however it only outputs the text for the last pair of delimiters. Any idea on how to tweak it? – Mark May 12 '11 at 18:52