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