As jthill explained, these are ansi escape codes
, which control how the terminal displays information, in a way somewhat similar to html tags. When inserted in a text stream they aren't displayed directly; instead they tell the terminal how to color and position the text on the screen.
But they're still just ascii characters like all the rest. When this text is viewed in a normal text reader, they become visible, since the reader doesn't know how to interpret them. Again, it's like when you view a raw html file.
apparently doesn't use escape codes in its output, and so when you run it stand-alone all you get is the plain text output. In fact the majority of programs, even when they do use escapes for formatting, are designed to not send them through pipes and redirects by default. That's why your single run and the looping solution works.
If I'm understanding it right, according to the watch
man page, by default it strips out any escape codes from the output of the command it's monitoring. But it obviously must also insert its own codes
into the output, since it wouldn't be able to control and update the display every few seconds without them. So when you pipe this output to a file, you're getting the escapes inserted from watch
along with the raw data from sensors