0

This is the text:

* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included

The output of this text should be this:

* Tue This is the first line

– info 1

– info 2

– info 3

NOTE: I have tried awk and sed but failed to come up with my output. The problem is that the START and END are the same ‘*’ (asterisk) and the first one should be included in the output.

0

I hope I understand this correctly. This script will remove everything from the line starting with the second * until the end of the buffer, producing your desired output from the example:

sed -n 'H;1h;$x;$s/\(\*[^*]*\)\n\*.*$/\1/p'

Explanation append all lines (H) to the hold buffer. For the last line exchange hold and pattern buffer ($x), so you have the whole file as one pattern. In this pattern the part to be kept is set in \(\) and kept (\1), while everything from the newline with * is deleted.

This fits your description, but if it doesn't fit all possible examples, you can modify the script.

0
perl -lne 'if ( m?^\*? ... m?^\*? ) { print if !// || !$a++ }'

sed -e '
   /^\*/!d
   :loop
       $q; N
   /\n\*/!bloop
   s/\(.*\)\n.*/\1/;q
'

sed -e '
   /^\*/!d
   :loop
      n
   //!bloop
   Q
'
0

Save sample text to the variable:

$ SAMPLE=$(cat <<EOF
* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included
* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included
EOF
)

Use awk to process your $SAMPLE:

$ awk '{if($1~"\*"){if(p==1){p=0;next}else{p=1}}if(p==1){print $0}}' <<<"$SAMPLE"
* Tue This is the first line

– info 1

– info 2

– info 3

* Tue This is the first line

– info 1

– info 2

– info 3

EDIT

As suggested in the comments there's surprisingly elegant awk solution:

$ awk '/^\*/{p=!p};p' <<<"$SAMPLE"
* Tue This is the first line

– info 1

– info 2

– info 3

* Tue This is the first line

– info 1

– info 2

– info 3

How it works:

  • /^\*/{p=!p}; - this will alternate the value of p to 1 and 0. It will become 1 when regex /^\*/ is first found. The second time it's found, p will become 0 and so on.

  • p - this is equivalent to p{print}. Since print is the default action in awk, it will always print when precondition evaluates to the true value, in this case when p becomes 1.

  • I feel this can be simplified to awk '/^\*/{p=!p} p' – Sundeep Mar 15 '17 at 7:49
  • 1
    Thank you for this awk sugar, I updated my answer. Please correct my comment on how it works if I got it wrong. – NarūnasK Mar 15 '17 at 12:07

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.