# \r carriage return in if



## SeventhSon (Jan 28, 2021)

Hi!

How to check in script that $var equal '\r' symbol?
tried

```
if [ $var = $'\010' ]
if [ $var =  '-r' ]
if [ "$var" = '\r' ]
```
- nothing works.
`echo $var|hexdump` is `000a`


----------



## Emrion (Jan 28, 2021)

You should specify the shell you use.

Concerning `echo $var|hexdump`, you just see the line feed that echo adds by default. Use `echo -n` to avoid this. It seems that your variable is empty.

With /bin/sh, this works:

```
#!/bin/sh

v=$'\r'
echo -n $v|hd
if [ $v = $'\r' ]; then echo "Ok"
fi
```


----------



## Snurg (Jan 28, 2021)

Another note.
\r equals  *carriage return* (CR, 0x0D, oct 10).
\n equals *linefeed* (LF, 0x0A)


----------



## SeventhSon (Jan 29, 2021)

Emrion said:


> You should specify the shell you use.
> 
> Concerning `echo $var|hexdump`, you just see the line feed that echo adds by default. Use `echo -n` to avoid this. It seems that your variable is empty.
> 
> ...


ok, I ran you script and got this:
`0000000 5c24 0072                             
0000003
Ok`

so, in hex '\r' is "5c24 0072" (?!?)
I have opposite, in hex "000a"
now you see?


----------



## Emrion (Jan 29, 2021)

With this script I get:

```
00000000  0d                                                |.|
00000001
Ok
```

So there is something peculiar in your configuration.
What does `locale` return?


----------



## ralphbsz (Jan 29, 2021)

SeventhSon said:


> ok, I ran you script and got this:
> `0000000 5c24 0072
> 0000003
> Ok`


Something is wrong here. The default output format of the "hd" command (which is the executable as hexdump, but when called as "hd" it acts differently) is canonical, meaning individual bytes, followed by the ASCII transcription. You must have used "hexdump" instead, which default to outputting 16-bit words. And note that the 16-bit words are printed as big-endian, while the ASCII data is by construction little-endian, so we need to pairwise swap bytes. For fun, try this: "echo -n abc | hexdump", and you get "0000000 6261 0063", showing how the bytes are swapped.



> so, in hex '\r' is "5c24 0072" (?!?)


Let's decode that string. To get an ASCII decoding chart, do "man ascii". So what you have here (remember the byte swapping): 24 = $, 5c=\, and 72=r. So the string is set to "$\r". Something went wrong with your quoting.

Which brings up a question for emrion: Why is there a $ in "v=$'\r'? The $ sign usually means: expand this variable name. But '\r' is not a variable name. I think you mean "v='\r'". Now, what that means depends heavily on which shell you use! The quoting and expansion rules depend on the shell.

What's even worse: There are many different versions of echo. There is one in /bin/echo on FreeBSD. That one doesn't seem to allow backslash expansion. Most shells have a built-in version of echo, which act different. For example, I use bash as my login shell, and here is the section from the bash man page about echo:

```
echo [-neE] [arg ...]
        Output the args, separated by spaces, followed by a newline.
        The return status is 0 unless a write error occurs.  If -n is
        specified, the trailing newline is suppressed.  If the -e option
        is given, interpretation of the following backslash-escaped
        characters is enabled.  The -E option disables the
        interpretation of these escape characters, even on systems where
        they are interpreted by default.  The xpg_echo shell option may
        be used to dynamically determine whether or not echo expands
        these escape characters by default.  echo does not interpret --
        to mean the end of options.  echo interprets the following
        escape sequences:
...
              \r     carriage return
...
```


----------



## Emrion (Jan 29, 2021)

With v='\r', I get:

```
00000000  5c 72                                             |\r|
00000002
```

You should try by yourself ralphbsz. The shell is /bin/sh for me (pretty obvious if you read the code I posted) and the echo command used here is shell integrated.


----------



## olli@ (Jan 29, 2021)

In bourne shell syntax, an ASCII CR (decimal 13, hex 0x0D or `'\r'` in C syntax) is written as `$'\r'`. This works in all major bourne-compatible shells, including zsh, bash and FreeBSD’s /bin/sh.
 
If a shell variable VAR contains characters like ASCII CR, you must put them in double quotes in order to expand them properly, like `"$VAR"`.
 
The following shell script demonstrates how it can be done. It uses two different methods to set two variables to ASCII CR, the first uses awk(1), the second uses shell syntax. The result should be the same.

```
#!/bin/sh -

VAR1=$(awk 'BEGIN {printf "%c", 13}')
VAR2=$'\r'

echo -n "$VAR1" | hd
echo -n "$VAR2" | hd

if [ "$VAR1" = "$VAR2" ]; then
        echo equal
else
        echo different
fi
```
It produces the following output:

```
00000000  0d                                                |.|
00000001
00000000  0d                                                |.|
00000001
equal
```
If it doesn’t work for you, then your variable contains something else. You can check with hd(1), as others have already suggested.
 
By the way, there are many more ways to produce ASCII CR in shell scripts. Here are more examples:

```
VAR=$(echo -e '\r')
VAR=$(echo x | tr x '\r')
VAR=$(python -c 'print(chr(13))')
```


----------



## olli@ (Jan 29, 2021)

SeventhSon said:


> ok, I ran you script and got this:
> `0000000 5c24 0072`


Obviously you forgot the `$` sign, or you quoted the `$` sign, or used the wrong kind of quote characters, or some other mistake. It must be exactly `v=$'\r'`. If that still doesn’t work, then something must be seriously wrong with your shell.


----------



## SirDice (Jan 29, 2021)

FreeBSD and, as far as I know, a lot of Linux' have a printf(1) command. The format string works just like its C printf(3) counterpart. 


```
% printf "\n" | hd
00000000  0a                                                |.|
00000001
```


----------



## olli@ (Jan 29, 2021)

SirDice said:


> FreeBSD and, as far as I know, a lot of Linux' have a printf(1) command. The format string works just like its C printf(3) counterpart.


Yes, it works fine with `'\n'`, but you have  to be careful with format characters: `printf "%c" 13` does _not_ produce the expected result (it interprets `13` as a character string, not as an integer). If you need to do something like that, then you can use awk(1), for example – `awk 'BEGIN {printf "%c", 13}'` produces the expected result.

As several people have mentioned, the easiest way to get an ASCII CR character in a shell script is by using the dollar-single-quote syntax: `$'\r'`
It’s also commonly used for newline characters, like `NL=$'\n'`, or for control sequences, like color attributes:

```
if [ -t 1 ]; then
        RED=$'\e[31m'
        OFF=$'\e[m'
else
        RED=""
        OFF=""
fi
echo "${RED}Print something in red.${OFF}"
```


----------

