Axe
Axe

Reputation: 113

Interpret carriage returns programatically in bash

When bash displays strings, it interprets the carriage return '^M'

$ echo "1234^Mab"
ab34

I have a script that needs access to the interpreted string "ab34". But I can't find any way to do this. The output stream of the echo command still contains the carriage return character, which means that if a script reads the output, it will still see "1234^Mab", even though the shell displays the string "ab34".

Removing the carriage return is not good enough; It does not result in the string "ab34".

$ echo "1234^Mab" | tr -d '\r'
1234ab

Converting the carriage return to a unix-style newline character doesn't produce the desired result either:

$ echo "1234^Mab" | sed 's/^M/\n/'
1234
ab

Upvotes: 1

Views: 2334

Answers (2)

Barmar
Barmar

Reputation: 780663

Use the col -b command to interpret cursor control sequences and return the visible output.

echo $'1234\rab' | col -b

This handles about a dozen different cursor motion sequences, not just carriage return.

Upvotes: 7

Mat
Mat

Reputation: 206659

Here's a script that "emulates" the carriage-return by processing the input argument character by character. The output is built character by character too, resetting the output index when CR is encountered.

#! /bin/bash

arg="$1"
out=""
cr=$'\r'

j=0
for ((i=0; i<${#arg}; i++)) ; do
  char=${arg:$i:1}
  if [[ $char = $cr ]] ; then
    j=0
  else
    tmp="${out:0:$j}"$char
    ((j++))
    out="$tmp${out:$j}"
  fi
  # echo "$out" # to see it in progress
done
echo "Final: $out"

Example:

$ ./t.sh 123456$'\r'abcde$'\r'.:.
1
12
123
1234
12345
123456
123456
a23456
ab3456
abc456
abcd56
abcde6
abcde6
.bcde6
.:cde6
.:.de6
Final: .:.de6

Upvotes: 0

Related Questions