\r carriage return in if

SeventhSon

New Member


Messages: 4

Hi!

How to check in script that $var equal '\r' symbol?
tried
Code:
if [ $var = $'\010' ]
if [ $var =  '-r' ]
if [ "$var" = '\r' ]

- nothing works.
echo $var|hexdump is 000a
 

Emrion

Aspiring Daemon

Reaction score: 155
Messages: 544

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:
Code:
#!/bin/sh

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

Snurg

Daemon

Reaction score: 426
Messages: 1,053

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

SeventhSon

New Member


Messages: 4

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:
Code:
#!/bin/sh

v=$'\r'
echo -n $v|hd
if [ $v = $'\r' ]; then echo "Ok"
fi
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

Aspiring Daemon

Reaction score: 155
Messages: 544

With this script I get:
Code:
00000000  0d                                                |.|
00000001
Ok


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

ralphbsz

Son of Beastie

Reaction score: 1,872
Messages: 2,866

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:
Code:
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

Aspiring Daemon

Reaction score: 155
Messages: 544

With v='\r', I get:
Code:
00000000  5c 72                                             |\r|
00000002


You should try by yourself [USER=30524]ralphbsz[/USER]. 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@

Aspiring Daemon
Developer

Reaction score: 1,011
Messages: 963

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.
Code:
#!/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:
Code:
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:
Code:
VAR=$(echo -e '\r')
VAR=$(echo x | tr x '\r')
VAR=$(python -c 'print(chr(13))')
 

olli@

Aspiring Daemon
Developer

Reaction score: 1,011
Messages: 963

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

Administrator
Staff member
Administrator
Moderator

Reaction score: 10,164
Messages: 35,668

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.

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

olli@

Aspiring Daemon
Developer

Reaction score: 1,011
Messages: 963

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:
Code:
if [ -t 1 ]; then
        RED=$'\e[31m'
        OFF=$'\e[m'
else
        RED=""
        OFF=""
fi
echo "${RED}Print something in red.${OFF}"
 
Top