How to assert that a string has a newline character and, if so, remove it

The problem is that you have an embedded Carriage-Return (CR, \r). This causes the terminal text-insertion point to kick back to the start of the line it is printing. That is why you are seeing the 'hello' at the start of the line in you $newVAR example - sed -n l displays a readable view of unprintable characters (and end of line).

var=ab$'\r'c ; echo "$var";  printf %s "$var" | sed -n l
# output:
cb
ab\rc$

You can test for it with a simple bash condition check:

[[ $var == *$'\r'* ]] && echo yes || echo no
# output:
yes

You can combine the test and fix in one step by testing for \r(s) and removing them via:

fix="${var//$'\r'/}"; echo "$var"; echo "$fix"
# output:
cb
abc

The fix uses Shell Parameter Expansion. The particular form used above is for replacing substrings based on your proovided pattern: ${parameter/pattern/string} <-- This replaces only the first found pattern with string in variable named *parameter. To replace all patterns, you just need to change the first / to //.


You can represent \r as $'\r' in bash:

if [ "$myvar" = "hello"$'\r' ]; then
    echo they are equal
else
    echo they are not equal
fi

Or chop the last \r in myvar:

if [ "${myvar%$'\r'*}" = "hello" ]; then
    echo they are equal
else
    echo they are not equal
fi

Curiously, in many shells getopts is a very likely candidate for a job like this. This may seem counterintuitive at first, but if you consider that getopts' primary function is to recognize and offer up for interpretation as many specified single character command-line options as might be found in a concatenated series of same, it might begin to make a little more sense.

To demonstrate, from a bash shell:

x=$(printf '\n\r%010s\t' hello)
OPTIND=1
while  getopts : na "-$x"
do     printf %q\\n "$OPTARG"
done

$'\n'
$'\r'
\
\
\
\
\
h
e
l
l
o
$'\t'

In that way it can sometimes be convenient to allow getopts to handle the disassembly as a sort of shell auto-pilot for cases like this. When you do so, you can just screen out unwanted bytes w/ a case or [ test ] and build your string back-up from byte 1:

OPTIND=1 y=$(printf \\n\\r) z=
while  getopts : na "-$x"
do     case $OPTARG in ([!$y])
            z=$z$OPTARG
       esac
done
printf %q\\n "$z"

$'     hello\t'

Given this simple example case - and given a shell which supports the parameter expansions already elsewhere mentioned - said expansions will probably serve you better here. But I thought getopts might be worth a mention as well in case you weren't aware of its capabilities in this respect. Certainly when I learned of it I found many useful applications for it, anyway.

Tags:

String

Bash