8

This question asks about wrapping text at a certain column, and people suggest using fold or fmt but as far as I can see, these simply count characters and don't allow for non-printing characters. For example:

fold -w 20 -s <<<`seq 1 25`

as one might expect, produces:

1 2 3 4 5 6 7 8 9 
10 11 12 13 14 15 
16 17 18 19 20 21 
22 23 24 25

but:

fold -w 20 -s <<<^[[32m`seq 1 25`^[[m

(where ^[ is the escape character) intuitively ought to produce the same thing in green text, but instead produces:

1 2 3 4 5 6 7 
8 9 10 11 12 13 14 
15 16 17 18 19 20 
21 22 23 24 25

in green text.

I can't see any switches that say to account for non-printing characters, and the PS1 approach to flagging non-printing characters doesn't seem to work with fold or fmt.

Is there something (ideally something standard) that can wrap text whilst accounting for non-printable characters?


EDIT:

The example above is really to simplify and demonstrate the problem but I may have over-simplified. To clarify my real-world example, I've got text where some words are in colour (using ANSI escape sequences) and I'd like that to wrap neatly. For example:

Here is some example text that contains ^[[31mred^[[m and ^[[32mgreen^[[m words that I would like to wrap neatly.

where ^[ is the escape character.

If I wanted this to wrap to 20 columns, I would expect:

Here is some
example text that
contains red and
green words that
I would like to
wrap neatly.

(with "red" and "green" in colour) but because of the ANSI escape codes, it wraps thus:

Here is some
example text
that contains
red and
green words
that I would like
to wrap neatly.
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
IpsRich
  • 767
  • Have you found an answer to this? I'm having trouble with my script - each entry is either red or green and I want to fold it at 80 characters but when accounting for all the color/escape codes it ends up wrapping at like 30 (visible) characters – 19wolf Jul 04 '20 at 05:18
  • I never found a command that will do this for me, unfortunately. The best I managed was to pipe my coloured output into a Perl script, which then inserts line breaks at suitable places. – IpsRich Jul 06 '20 at 07:06

1 Answers1

2

The ANSI escape sequence is being interpreted by the shell, not by the piping. So you're really inserting the text ^[[32m alongside with your sequence-output into you fold-command. If you want the whole text in green, you could try something like this:

echo -e "\e[32m"$(seq 1 25 | fold -w 20 -s)"\e[m"

or

echo -e "\e[32m"; seq -s ' '  1 25 | fold -w 20 -s; echo -e "\e[m"

Note that I'm using the \e as the escape character. This works directly within bash shells for testing.

Stefan M
  • 1,616
  • 1
    Thanks for the reply. I was really just trying to provide a simple example to demonstrate the problem. My real example involves words where some of them are in colour. Apologies if I over-simplified the problem. I'll edit the question to clarify. – IpsRich Feb 14 '18 at 09:37
  • Still, if you insert ANSI escape sequence characters into other commands, they will be treated as normal characters. The will only be interpreted by the shell (which, as far as I can tell, is your core problem). – Stefan M Feb 14 '18 at 09:40
  • 4
    Some commands can cope though (e.g. less -R), so I was hoping fold or fmt might too. – IpsRich Feb 14 '18 at 09:49
  • Faced with the exact same situation here. I ended up using special character sequences in the text to mark where the ANSI escape sequences would eventually go, with the key point being that the placeholders were really short. Then I could run fmt on the text to handle wrapping, and do simple substitution on the result with sed to swap out the placeholders with the actual escape sequences. – Ti Strga May 16 '23 at 20:42