Search code examples
bashcarriage-return

Why is my echo command writing two words over each other?


I have a bash script which picks two words and (should) concatenate them.

#!/bin/bash

adj="$(shuf -n1 adjectives.txt)"
noun="$(shuf -n1 nouns.txt)"

echo ADJ $adj
echo NOU $noun

echo "$adj $noun"

The variables are being set correctly, but for some reason, the final echo doesn't work right. For instance:

ADJ humbler
NOU lyric
 lyricr

Or:

ADJ bipinnate
NOU lipases
 lipasese

What's happening here is that the final output is the adjective's last letter at the end of the noun. Why is this, and how can I stop it?

There is an Asciinema of this phenomenon here: https://asciinema.org/a/199297


Solution

  • Your input files most likely have CRLF (\r\n) line endings. The \r (carriage return) will cause the output to jump back to the first column of the current line, as your concatenation gets rid of the \n and not the \r.

    That is the format used by Windows/DOS.

    You can either convert the files, or you can strip it out using tr, e.g.:

    adj="$(shuf -n1 adjectives.txt | tr -d '\r')"
    noun="$(shuf -n1 nouns.txt | tr -d '\r')"
    

    You can also run this across the files instead, e.g.:

    tr -d '\r' < adjectives.txt > adjectives-reformatted.txt