I'm going to submit form using cURL, where some of the contents is come from other file, selected using sed

If param1 is line matching pattern from other file using sed, below command will works fine:

curl -d param1="$(sed -n '/matchpattern/p' file.txt)" -d param2=value2 http://example.com/submit

Now, go to the problem. I want show only text between 2 matching pattern excluding the matching pattern itself.

Lets say file.txt contains:

Bla bla bla
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

Currently, lots of "beetween 2 matching pattern" sed command won't remove firstmatch and secondmatch.

I want the result to become:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.

Here is one way you could do it:

sed '1,/firstmatch/d;/secondmatch/,$d' 

Explained: From the first line to the line matching firstmatch, delete. From the line matching secondmatch to the last line, delete.


The other sed solution will fail if firstmatch occurs on the 1st line1.

Keep it simple, use a single range and an empty2 regex:
either print everything in that range excluding range ends (auto-printing disabled)3:

sed -n '/firstmatch/,/secondmatch/{//!p;}' infile

or, shorter, delete everything not in that range and also delete the range ends:

sed '/firstmatch/,/secondmatch/!d;//d' infile

1: The reason being that if the second address is a regexp, then checking for the ending match will start with the line following the line which matched the first address.
Therefore, /firstmatch/ is never evaluated for the 1st line of the input, sed will simply delete it as it matches the line number in 1,/RE/ and move on to the 2nd line where it checks if the line matches /firstpattern/

2: When a REGEX is empty (i.e. //) sed behaves as if the last REGEX used in the last command applied (either as an address or as part of a substitute command) was specified.

3: the ;}syntax is for modern sed implementations; with older ones use either a newline instead of the semicolon or separate expressions e.g. sed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile

  • Can you explain what // is doing (inside the {…})? Mar 15 '18 at 0:50
  • Thanks, but you fell into my trap. I know that // means the last regular expression used; from everything that I’ve read, that should be /secondmatch/. I’ve verified through testing that your command works, and so I’ve concluded that it is functioning as /firstmatch|secondmatch/ (which you have confirmed), but I can’t find any documentation (not even the POSIX document that you linked to or the GNU sed manual) that describes this behavior.  … (Cont’d) Mar 15 '18 at 16:43
  • (Cont’d) …  Entertaining experiments: (I) In sed: (1) If I do /first/,4, then // acts like /first/.  (2) If I do 2,/second/, then // gets a “no previous regular expression” error.  (I find this a blatant failure to follow the specified behavior.)  (3) Adding --posix doesn’t change either of the above.  (II) In other programs: (4) In vi, after /first/,/second/, // acts like /second/ (and the other forms are also rational implementations of the documented rule).  … (Cont’d) Mar 15 '18 at 16:43
  • (Cont’d) …  (5) awk seems to have no notion of “the last RE used”; // refers to the non-character before or after any character. (I invite you to try echo -- | awk '{ gsub(//, "cha"); print }'.) Mar 15 '18 at 16:43
  • So, you read “the last REGEX used in the last command” as “the last REGEX(s) used in the last command” and so you (correctly) guessed that it meant /first|second/.  Lucky you.  I mention the other programs to demonstrate that this is not some system-wide regex convention.  Whoever added it to sed didn’t bother to add it to vim, where it would have made just about as much sense.   :-)   ⁠ Mar 15 '18 at 17:13

In awk:

awk '
  $1 == "secondmatch" {print_me = 0}
  print_me {print}
  $1 == "firstmatch {print_me = 1}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.