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
  • 66,199
  • 35
  • 114
  • 250
IpsRich
  • 737
  • 6
  • 17
  • 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 – Eric Wolf 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,606
  • 1
  • 12
  • 20
  • 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