How to loop through character in string and still detect null char in Bash

Viewed 155

I have this function:

function convert_ascii_string_to_decimal {
    ascii=$1
    unset converted_result

    while IFS="" read -r -n 1 char; do
        decimal=$(printf '%d' "'$char")
        echo $decimal
        converted_result="$converted_result $decimal"
    done < <(printf %s "$ascii")
    converted_result=$(echo $converted_result | xargs) #strip leading and trailing
}

It is meant to take an ascii string variable, loop through every character, and concatenate the ascii decimal representation to a string. However, this while loop seems to ignore null chars, ie characters with ascii 0. I want to be able to read every single ascii there is, including null.

2 Answers

To get all characters of a string as decimal number, you can use hexdump to parse a string:

 echo -e "hello \x00world" | hexdump -v -e '1/1 "%d "'
 104 101 108 108 111 32 0 119 111 114 108 100 10 

This also works for parsing a file:

echo '05 04 03 02 01 00 ff' | xxd -r -ps  > file
hexdump --no-squeezing --format '1/1 "%d "' file 
5 4 3 2 1 0 255

hexdump explanation:

  • options -v and --no-squeezing prints all bytes (without skipping duplicated bytes)
  • options -e and --format allows giving a specific format
  • format is 1/1 "%d " which means
    • Iteration count = 1 (process the byte only once)
    • Byte count = 1 (apply this format for each byte)
    • Format = "%d" (convert to decimal)

You can't store the null character in a bash variable, which is happening in your script with the $char variable.

I suggest using xxd instead of writing your own script:

echo -ne "some ascii text" | xxd -p

If we echo a null charcter:

$ echo -ne "\0" | xxd -p
00
Related