LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Hex compare in shell (https://www.linuxquestions.org/questions/linux-newbie-8/hex-compare-in-shell-4175444596/)

nicksu 01-07-2013 10:01 PM

Hex compare in shell
 
Hi

Can anybody show me how to compare Hex number in shell?
I define A=`grep log artifact|cut -d":" -f3`,and it echos the A is 0x5a,and how can I do to compare whether it equals 0x5a or not?
I tried == and -eq but both in vain.
Thank you

Snark1994 01-08-2013 08:59 AM

'==' should work - '0x5a' is not a byte, it's a string.

Code:

$ B='\x5a'
$ echo $B
Z
$ A='0x5a'
$ echo $A
0x5a
$ if [[ $A == '0x5a' ]]; then echo "Equal"; fi
Equal

Does that answer your question?

nicksu 01-08-2013 09:22 PM

Quote:

Originally Posted by Snark1994 (Post 4865392)
'==' should work - '0x5a' is not a byte, it's a string.

Code:

$ B='\x5a'
$ echo $B
Z
$ A='0x5a'
$ echo $A
0x5a
$ if [[ $A == '0x5a' ]]; then echo "Equal"; fi
Equal

Does that answer your question?

Hi Sir,when I define the value of A like you do,it is ok.but if I fetch the value from a command,it is wrong again as below:

Code:

[ssh@localhost hctest]$ A=0x5a
[ssh@localhost hctest]$ if [[ $A == '0x5a' ]];echo compliant;fi
-bash: syntax error near unexpected token `fi'
[ssh@localhost hctest]$ if [[ $A == '0x5a' ]]; then echo compliant; fi
compliant
[ssh@localhost hctest]$ A=`grep -iw port artifact|grep -v ^*|awk -v FS=" " '{print $3}'`
[ssh@localhost hctest]$ echo $A
0x6300
[ssh@localhost hctest]$ if [[ $A == '0x6300' ]]; then echo compliant; fi


Snark1994 01-09-2013 04:13 AM

Hm, I haven't seen that before. What does

Code:

echo ${#A}
say? And is 'artifact' a file? If so, can you post it?

nicksu 01-09-2013 04:34 AM

Quote:

Originally Posted by Snark1994 (Post 4865981)
Hm, I haven't seen that before. What does

Code:

echo ${#A}
say? And is 'artifact' a file? If so, can you post it?

Sir,it shows 7,could you told me why it shows 7? yup,artifct is a regular file,sorry that cannot show it all out,but the line which match my grep shows as below:
Code:

** Some port to listen on:
    Port    REG_DWORD    0x6300

Appreciate your reply,thank you man!

David the H. 01-09-2013 04:08 PM

Code:

A=`grep -iw port artifact|grep -v ^*|awk -v FS=" " '{print $3}'`
This is an unnecessary string of greps, when awk can do it all single-handed.

Code:

A=$( awk '/Port.*REG_DWORD/ { print $3 }' )
Or something similar.
($(..) is highly recommended over `..`)

Is it certain that there will always be only one line that matches though? If anything other than the field you want gets into the output you're not going to get a match. So when debugging code, you should start by echoing your variables, preferably with some kind of brackets around them to make any whitespace visible.

Another possibility is the line ending. This looks like the output of a windows registry or somesuch, and if the file has dos-style line endings, the invisible carriage return could be ending up tacked onto the end of the field. Try running it through cat -A:

Code:

echo "[$A]" | cat -A

nicksu 01-09-2013 10:23 PM

Quote:

Originally Posted by David the H. (Post 4866477)
Code:

A=`grep -iw port artifact|grep -v ^*|awk -v FS=" " '{print $3}'`
This is an unnecessary string of greps, when awk can do it all single-handed.

Code:

A=$( awk '/Port.*REG_DWORD/ { print $3 }' )
Or something similar.
($(..) is highly recommended over `..`)

Is it certain that there will always be only one line that matches though? If anything other than the field you want gets into the output you're not going to get a match. So when debugging code, you should start by echoing your variables, preferably with some kind of brackets around them to make any whitespace visible.

Another possibility is the line ending. This looks like the output of a windows registry or somesuch, and if the file has dos-style line endings, the invisible carriage return could be ending up tacked onto the end of the field. Try running it through cat -A:

Code:

echo "[$A]" | cat -A

Thank you Sir,it finially solve my problem,when I used cat -A,it shows a "^M" at the end of the value,but a "$" in stead in the value which I explicitly define as A="0x6300",it is the difference between Windows and Unix' text format.and after I used the tr -d '\r',the "==" work,and it exactly work.So appreciate for your help.

chrism01 01-10-2013 12:51 AM

Actually for file conversions, you can use the dos2unix & unix2dos cmds
http://linux.die.net/man/1/unix2dos

David the H. 01-11-2013 04:40 AM

cat -A displays non-printing ascii characters in caret notation format, except for LF (line feed,\n) line-endings, which are represented with "$". "^M" is of course the caret notation for CR (carriage return,\r).

(If you weren't aware, the dos line format uses CRLF, while unix uses LF only. awk expects unix style, which is why you end up with an extra carriage return at the end of the line.)

There are any number of ways to convert between the two, from stand-alone programs like tofrodos, to simple tr, sed, or awk commands, or anything really that can process text. There's really no correct or best way.

You could even do it in the shell with a simple parameter substitution.

Code:

A=${A%.}            #removes the final character, no matter what it is

shopt -s extquote    #uses bash's ascii-style quoting to only target CRs
A=${A%$'\r'}        #safer than the above, but less portable

In awk you could even simply set the input record separator so that it can handle either input format (the output is unix-style by default).

Code:

awk -v RS='\r?\n' '/Port.*REG_DWORD/ { print $3 }'

theNbomr 01-11-2013 10:28 AM

A lot of this thread seems to arise from the misunderstanding of the distinction between the value of a byte and the representation of that value. A byte is eight ordered bits, and has the same value irrespective of how we represent it. The representation commonly reflects the context of usage, but never affects the value.
A problem arises when people use terminology like 'Hex number' which is a mixture of terms. A number is a number, and has a value. Its representation may be in many forms, of which one is hex. The problem is that expressing the representation as part of the problem implies that we must treat the data as string/character, since that is the only way to represent data in any radix-specific context. If the data is not string/character data, then expressing the radix is irrelevant.
Whenever there is any question about the nature of some data, I find it useful to display the data using od. I prefer to represent the data in hex, since that tends to be context agnostic. Reperesenting it as character/text can lead to confusion, since some characters have particular meanings in some contexts, line-endings like Carriage-returns and Linfeeds in particular. od quickly and unambiguously exposes these, displaying CRs and LFs in hex as 0D and 0A, respectively. I like to use the form
Code:

od -tx1 someArbitraryFile
Article #2 of this thread seizes on this concept immediately, but the real problem seems to come down to the use of DOS oriented line terminators. These can be quickly found with od.
The problem gets somewhat compounded (and becomes more confounding) when some programming languages silently convert our strings that represent numbers (like here; '0x6300') into integer or floating point scalar variables. It often isn't clear which interpretation a language will make. For instance in article two of this thread, Snark1994 gives the example
Code:

$ B='\x5a'
$ echo $B
Z
$ A='0x5a'
$ echo $A
0x5a
$ if [[ $A == '0x5a' ]]; then echo "Equal"; fi
Equal

This is supposed to demonstrate how bash (or some shell, I presume) makes the interpretation. However in my bash shell (GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu) ), I get
Code:

$ B='\x5a'
$ echo $B
\x5a

What's up with that?

--- rod.

David the H. 01-11-2013 11:04 AM

the echo command in bash doesn't automatically expand hex values, or any other backslash references, by default. That's what the -e option is for. (The '%b' token in printf also expands them.)

But you can also turn expansion on globally with the xpg_echo shell option. Then you can use the -E to disable it locally.

Code:

$ B='\x5a'

$ echo "$B" ; echo -e "$B" ; printf '%b\n' "$B"
\x5a
Z
Z

$ shopt -s xpg_echo ; echo "$B" ; echo -E "$B"
Z
\x5a

Another choice is to use the $'..' quoting mechanism. But you can't use that with variables, since it otherwise acts like a hard-quote. You'd have to use it when setting the variable, and the resulting contents would be the expanded value.

Code:

$ B=$'\x5a'
$ echo "$B"
Z

Some other shells might have different behavior. The POSIX echo specification doesn't define any arguments for it, so its up to the individual shell.

Snark1994 01-12-2013 03:43 PM

Quote:

Originally Posted by theNbomr (Post 4867855)
For instance in article two of this thread, Snark1994 gives the example
Code:

$ B='\x5a'
$ echo $B
Z
$ A='0x5a'
$ echo $A
0x5a
$ if [[ $A == '0x5a' ]]; then echo "Equal"; fi
Equal

This is supposed to demonstrate how bash (or some shell, I presume) makes the interpretation. However in my bash shell (GNU bash, version 4.1.5(1)-release (i486-pc-linux-gnu) ), I get
Code:

$ B='\x5a'
$ echo $B
\x5a

What's up with that?

--- rod.

Sorry, I was using zsh, and may well have options set in my .zshrc which change zsh's default behaviour on this issue anyway...

Thanks for the 'od' tip, I often find it frustrating when debugging bash to work out what /exactly/ a variable contains...


All times are GMT -5. The time now is 03:37 AM.