2

Recently I encountered the great fortune command and use it now to send a nightly quote to a persistent chat.

Now I wonder how to remove the forced line breaks for the quote part, but preserve them around the author line at the end.

Why? Because of the chat windows' varying widths, the resulting output is double line breaked in most cases (this was not expressed well, but you may have understood what I mean - if not and this is important for you, feel free to ask for clarification).

Of course I searched for a solution already and found:

echo -n `fortune`

but this removes all line breaks obviously.

Most appreciated would be a sh compatible solution, but in case of largely increased simplicity, bash (others?) would be an option as well.


Update 2016-02-12:

Sample of multi-line fortune output, as requested:

me@myhost:~$ fortune
Mit jemand leben oder in jemand leben, ist ein großer 
Unterschied. Es gibt Menschen, in denen man leben kann, ohne mit 
ihnen zu leben, und umgekehrt. Beides zu verbinden, ist nur der 
reinsten Liebe und Freundschaft möglich.
        -- Goethe, Maximen und Reflektionen, Nr. 649
me@myhost:~$ 

The proposed solution below does this:

me@myhost:~$ fortune | sed ':a;N;$!ba;s/\n[[:space:]]\{2\}--/ --/'
Die so genannten Naturdichter sind frisch und neu aufgeforderte, 
aus eine rüberbildeten, stockenden, manierierten Kunstepoche 
zurückgewiesene Talente. Dem Platten können sie nicht ausweichen, man 
kann sie daher als rückschreitend ansehen; sie sind aber 
regenerierend und veranlassen neue Vorschritte. -- Goethe, Maximen und Reflektionen, Nr. 258
me@myhost:~$ 

This is quite a good proposal, while not providing the exact wished solution. It does the opposite of what I am trying to achieve. As soon as I understand the sed expression, I will try to invert the logic ... feel free to be faster than me! :D

  • 2
    Do you have an example of sample input, and expected output? "Around" the author bit sounds like a newline before and after the last line? – thrig Feb 11 '16 at 18:06
  • Correct, thrig, this is exactly what I am trying to achieve! – Nicolas Feb 12 '16 at 19:19
2
echo $(fortune) | sed 's/-- /\n    -- /'

Insert however many leading spaces you want before the author line. This simply uses echo to strip the carriage returns, then replaces the author prefix with a newline and the author prefix.

  • Ough this is so awesomly simple - now I feel stupid because I did not found this; thank you very much! – Nicolas Feb 13 '16 at 19:09
0

This is mostly stolen from here:

fortune | sed ':a;N;$!ba;s/\n[[:space:]]\{2\}--/ --/'

From the original answer:

Explanation:

  1. Create a label via :a.
  2. Append the current and next line to the pattern space via N.
  3. If we are before the last line, branch to the created label $!ba ($! means not to do it on the last line as there should be one final newline).

The final step is the only one I modified. Since the pattern is two concatenated lines, search for -- preceded by two or more whitespaces and a newline (AFAIK this pattern only shows up on quotes). Replace the newline with a single space and add back in the -- that was removed.

Before:

There is always one thing to remember: writers are always selling somebody out.    
            -- Joan Didion, "Slouching Towards Bethlehem"

After:

There is always one thing to remember: writers are always selling somebody out. -- Joan Didion, "Slouching Towards Bethlehem"
  • Thank you for this proposed solution. In fact, it does the opposite of what I am trying to do - which is good as the differentiating logic between the author's line and the citate lines seem to work well! Note that there are shorter and longer fortune outputs - the longer ones show more clearly what I mean. I updated my question with sample outputs. – Nicolas Feb 12 '16 at 19:22
  • I completely misread the question somehow and thought this is what you were asking for! Sorry about that. Instead of trying to modify this to do what you actually want, I recommend going with Jeff's solution. It works and is much easier to understand. – hairlessbear Feb 12 '16 at 20:53
  • Never mind, I appreciate your input anyway, as it teached me sed mechanisms I never heard of - it's good to have them in mind! – Nicolas Feb 13 '16 at 19:28
0

One could treat the file as a single string, then only replace newlines that are followed by two newlines. This solution assumes non-blank lines.

bash-4.1$ cat input 
duck
duck
duck
  -- goose
bash-4.1$ perl -0777 -ple 's/\n(?=[^\n]+\n[^\n]+\n)/ /g' input
duck duck duck
  -- goose
bash-4.1$ 

Another solution would be to build the lines into an array of lines in memory, then join that array with spaces, except for the final line, or to otherwise count how many lines there are first, then with that number determine when a newline should be converted to a space or left alone.

  • I tried your solution as well and it works as well! So sorry, but I prefer Jeffs solution because of the simplicity - thank you for your input nevertheless! – Nicolas Feb 13 '16 at 19:13

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.