Home > Net >  How to convert string to number in bash
How to convert string to number in bash

Time:08-10

So I have a file that has two lines in it. Both lines contain a number. I want to check if that number is a 0 or not and then echo it out if it is. However bash doesn't let me use the "-eq" operator and tells me the "integer expression expected" error.

I have tried using an array and then a for loop and if statement to loop through the values but it didnt work.

I have also tried using a while loop and loop through the lines in the file but got the same error.

Using string comparisons doesn't seem to work as it doesn't recognise the 0. So I would like to convert the strings to numbers if possible. Can someone advise please.

for i in `cat num.out`;do if [ "$i" -eq 0 ];then echo $i;fi;done

The file num.out contains two lines:

cat num.out
0
0

The file num.out was compiled using the parsed output of another internal company script

Per request:

cat -v num.out
^[[31m^[[1m0^[[0m
^[[31m^[[1m0^[[0m

hexdump -C num.out
00000000  1b 5b 33 31 6d 1b 5b 31  6d 30 1b 5b 30 6d 0a 1b  |.[31m.[1m0.[0m..|
00000010  5b 33 31 6d 1b 5b 31 6d  30 1b 5b 30 6d 0a        |[31m.[1m0.[0m.|
0000001e```

CodePudding user response:

First, don't read lines with a for loop as a general habit. Go back to the while. Second, SHOW the output you are getting in context. I use exactly the code and file above and it works fine.

I created the same file with carriage retruns, however, and get the error you mentioned.

$: printf "0\r\n0\r\n">num.out
$: for i in `cat num.out`;do if [ "$i" -eq 0 ];then echo $i;fi;done
: integer expression expected
0

Check your file.

$: tr -d $'\r' < num.out > clean
$: while read -r i; do if [[ "$i" == 0 ]]; then echo "i=$i"; fi; done < clean
i=0
i=0

or maybe use a regex that allows the CRLF ending.

$: while read -r i; do if [[ "$i" =~ ^0$'\r'?$ ]]; then echo "i=$i"; fi; done < num.out
i=0
i=0

EDIT

Thanks for KamilCuk's additional insights above.

I reproduced the original file and cleaned it.

$: cat -v num.out # note the ^[ escape codes below are single-bytes
^[[31m^[[1m0^[[0m^M
^[[31m^[[1m0^[[0m^M
$: sed -E 's/[[:cntrl:]]\[[0-9] m//g; s/\r$//;' num.out > clean
$: cat -v clean
0
0

For the record, my original solution was clumsy -

$: sed -E 's/^[[[0-9] m//g; s/^M$//;' num.out > clean # must use single-byte ^[ escape

This required inputting a literal escape code into the search pattern. The ^['s above are copy/paste representation artifacts using two characters, but I input them as one.

To do that, I usually set -o vi. That lets me use CTRL_V to escape the next character. I typed sed -E 's/<CTRL_V><ESC> to get that.

Thought that trick might help someone too, though.

Even better is the one mentioned in the comments, using the $'\e' syntax to quote the escapes (actually the whole sed script!), which is specitfic to the character itself, and doesn't require you remember the hex code. :)

$: sed -E $'s/\e\[[0-9] m//g; s/\r$//;' num.out > clean

Hope that helps.

CodePudding user response:

First approach: Remove the ANSI codes.

sed -e 's/\x1b\[[0-9;]*m//g' num.out | while read f; do test  "$f" -eq 0 && echo ">$f<"; done

Credit for the sed command:here

A variation of the first approach: Use grep instead of bash:

sed -e 's/\x1b\[[0-9;]*m//g' num.out | grep --color=never '^0$'

Another approach: Removing ANSI codes with ansifilter command:

ansifilter num.out | grep --color=never '^0$'

On Ubuntu, you can install it with sudo apt install -y ansifilter

  • Related