-1
# blah blah #  
#  
code  
code   
code  
code  
code  
code  
code  
#  

I'm looking for a sed to print all the code between to the two #'s.

Certain sections will have 6 lines of code others will have 15 lines or 11 lines.

sed -n '/blah/,/#/p' program.sh gives just blah and then the FIRST #.

Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
visedawk
  • 11
  • 1
  • [There](https://stackoverflow.com/help/formatting) you will find information on how to format your question with Markdown. – Cyrus Jun 23 '23 at 18:43
  • 1
    I think you should use a tool where it's easier to keep state, like [tag:awk] – Ted Lyngmo Jun 23 '23 at 19:04
  • See: [How to print lines between two patterns, inclusive or exclusive (in sed, AWK or Perl)?](https://stackoverflow.com/q/38972736/3776858) – Cyrus Jun 23 '23 at 20:52
  • If awk can do this, please show me (i will not die on the sed hill).... – visedawk Jun 23 '23 at 21:28
  • `awk '/blah/{s=1;next} /#/{s+=s;next} s==2'` – jhnc Jun 24 '23 at 04:20
  • Assuming the `#` are the only character on their own line, with GNU `sed`: `sed -n '/^#$/,/^#$/{/^#$/d;p}'` – Renaud Pacalet Jun 24 '23 at 06:00
  • I notice that none of the answers so far use `blah` anywhere. Please clarify your question to include examples of code that should **not** be output. – jhnc Jun 24 '23 at 21:27
  • your question title is unclear. What should print from this input `printf '# blah\n#\ncode\n'` ? – jhnc Jun 24 '23 at 21:33
  • what should print from this input? `printf '# blah\n#\ncode\n#\nx\n# not blah\n#\ncode\n#\n'` – jhnc Jun 24 '23 at 21:34
  • what should print if `blah` is separated from code? `printf '# blah\nx\ny\nz\n#\ncode\ncode\n#\n` – jhnc Jun 24 '23 at 21:36
  • should anything print here? `printf '# blah\n# not blah\n#\ncode\n#\n'` – jhnc Jun 24 '23 at 22:30
  • (in case it is not obvious, I am using `printf ...` as a command to produce the input, not as literal input) – jhnc Jun 24 '23 at 22:32

4 Answers4

0

This might work for you (GNU sed):

sed -n ':a;/#/{:b;n;//ba;p;bb}' file

If a line contains # fetch the next line and if that line also contains # repeat.

Otherwise, print the current line and repeat as above.

N.B. No lines before the first # will be printed and all lines until another # will be printed.

If the lines to be printed must be between two #'s, use:

sed -nE '/#/{:a;$b;N;/#.*\n.*#/!ba;h;s/^[^\n]*\n(.*)\n.*/\1/p;g;s/.*\n/\n/;D}' file

Print only the second occurrence:

sed -nE ':a;/#/{x;s/^/x/;/^x{2}$/!{x;b};x;:b;n;/#/ba;p;bb}' file
potong
  • 55,640
  • 6
  • 51
  • 83
0
awk '
    /^# *$/ && !f { f=1; next } 
    /^# *$/ && f { 
       for(i in a) print a[i]; exit 
    } 
    f { a[NR]=$0 }
' file
ufopilot
  • 3,269
  • 2
  • 10
  • 12
0

Using any awk:

$ awk '/^#/{if (++c%2) printf "%s", r; r=""; next} {r=r $0 ORS}' file
code
code
code
code
code
code
code
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

You could try this :

sed -n -e '/^#$/!d                                                                                                                                                                                      
           :loop
           n
           /^#$/q
           p
           b loop' program.sh

or, as a one-liner:

sed -n -e '/^#$/!d; :loop; n; /^#$/q; p; b loop' program.sh

Explanations:

/^#$/!d           .--------------------------------------------------.
                  | if the current line does not consist in a single |
   ^              | hash , delete it and start a new cycle           |
   |              .--------------------------------------------------.
   |                                      |
   |______________________________________/

At this point, the current line is composed of a single hash.

:loop  ----------------->  define loop label
       
  ^     n  ------------->  replace current line by next line
  |    
  |     /^#$/q  -------->  quit if we've found the second hash marker
  |    
  |     p  ------------->  otherwise print current line
  |    
  |     b loop
  |       |
  |_______/

UPDATE:

Perhaps I misunderstood your question. If what you need is to print a series of several blocks of instructions delimited by single hash markers, like this :

# blah blah #                                                                                                                                                                                  

Foo bar stuff thing
Lorem ipsum abracadabra ... 

#
code1 start
code1
code1
code1
code1
code1
code1 end 
#

Foo bar stuff thing
Lorem ipsum abracadabra ... 

#
code2 start
code2
code2
code2
code2
code2
code2
code2
code2
code2 end 
#

Foo bar stuff thing
Lorem ipsum abracadabra ... 

#
code3 start
code3
code3
code3
code3 end 
#

Foo bar stuff thing
Lorem ipsum abracadabra ...

then you can simply trade the "q" SED command for a "d" :

/^#$/!d                                                                                                                                                                                        
:loop
n
/^#$/d
p
b loop

Then, sed -n -e '/^#$/!d; :loop; n; /^#$/d; p; b loop' program.sh would return (based on the above data sample) :

code1 start
code1
code1
code1
code1
code1
code1 end
code2 start
code2
code2
code2
code2
code2
code2
code2
code2
code2 end
code3 start
code3
code3
code3
code3 end
Grobu
  • 599
  • 1
  • 11