Solução 1: atribuição de variável direta
Se tudo o que você está preocupado são os bytes nulos, então você deve ser capaz de ler diretamente os dados do arquivo em uma variável usando qualquer método padrão que preferir, ou seja, você deve ser capaz de simplesmente ignorar os bytes nulos e leia os dados do arquivo. Aqui está um exemplo usando o comando cat
e a substituição de comandos:
$ data="$(cat eeprom)"
$ echo "${data}"
MAC_ADDRESS=12:34:56:78:90,PCB_MAIN_ID=m/SF-1V/MAIN/0.0,PCB_PIGGY1_ID=n/SF-1V/PS/0.0,CSL_HW_VARIANT=D
Isso funcionou para mim dentro de um contêiner do Docker do BusyBox.
Solução 2: usando xxd
e for
loop
Se você quiser mais controle do que você pode usar xxd
para converter os bytes em seqüências de caracteres hexadecimais e iterar sobre essas seqüências de caracteres. Em seguida, ao interagir com essa string, você poderá aplicar a lógica que desejar, por exemplo, você poderia ignorar explicitamente os valores nulos iniciais e imprimir o restante dos dados até atingir alguma condição de quebra.
Aqui está um script que especifica uma "lista branca" de caracteres válidos (ASCII 32 a 127), trata qualquer subsequência de outros caracteres como um separador e extrai todas as subseqüências válidas:
#!/bin/sh
# get_hex_substrings.sh
# Get the path to the data-file as a command-line argument
datafile="$1"
# Keep track of state using environment variables
inside_padding_block="true"
inside_bad_block="false"
# NOTE: The '-p' flag is for "plain" output (no additional formatting)
# and the '-c 1' option specifies that the representation of each byte
# will be printed on a separate line
for h in $(xxd -p -c 1 "${datafile}"); do
# Convert the hex character to standard decimal
d="$((0x${h}))"
# Case where we're still inside the initial padding block
if [ "${inside_padding_block}" == "true" ]; then
if [ "${d}" -ge 32 ] && [ "${d}" -le 127 ]; then
inside_padding_block="false";
printf '\x'"${h}";
fi
# Case where we're passed the initial padding, but inside another
# block of non-printable characters
elif [ "${inside_bad_block}" == "true" ]; then
if [ "${d}" -ge 32 ] && [ "${d}" -le 127 ]; then
inside_bad_block="false";
printf '\x'"${h}";
fi
# Case where we're inside of a substring that we want to extract
else
if [ "${d}" -ge 32 ] && [ "${d}" -le 127 ]; then
printf '\x'"${h}";
else
inside_bad_block="true";
echo
fi
fi
done
if [ "${inside_bad_block}" == "false" ]; then
echo
fi
Agora podemos testar isso criando um arquivo de exemplo que tenha \x00
e \xff
subsequences separando substrings:
printf '\x00\x00\x00string1\xff\xff\xffstring2\x00\x00\x00string3\x00\x00\x00' > data.hex
E aqui está a saída que obtemos ao executar o script:
$ sh get_hex_substrings.sh data.hex
string1
string2
string3
Solução 3: usando os comandos tr
e cut
Você também pode tentar usar os comandos tr
e cut
para lidar com os bytes nulos. Aqui está um exemplo de extrair a primeira string terminada em nulo de uma lista de strings terminadas em nulo, comprimindo / colando caracteres nulos adjacentes e convertendo-os em novas linhas:
$ printf '$ data="$(cat eeprom)"
$ echo "${data}"
MAC_ADDRESS=12:34:56:78:90,PCB_MAIN_ID=m/SF-1V/MAIN/0.0,PCB_PIGGY1_ID=n/SF-1V/PS/0.0,CSL_HW_VARIANT=D
0#!/bin/sh
# get_hex_substrings.sh
# Get the path to the data-file as a command-line argument
datafile="$1"
# Keep track of state using environment variables
inside_padding_block="true"
inside_bad_block="false"
# NOTE: The '-p' flag is for "plain" output (no additional formatting)
# and the '-c 1' option specifies that the representation of each byte
# will be printed on a separate line
for h in $(xxd -p -c 1 "${datafile}"); do
# Convert the hex character to standard decimal
d="$((0x${h}))"
# Case where we're still inside the initial padding block
if [ "${inside_padding_block}" == "true" ]; then
if [ "${d}" -ge 32 ] && [ "${d}" -le 127 ]; then
inside_padding_block="false";
printf '\x'"${h}";
fi
# Case where we're passed the initial padding, but inside another
# block of non-printable characters
elif [ "${inside_bad_block}" == "true" ]; then
if [ "${d}" -ge 32 ] && [ "${d}" -le 127 ]; then
inside_bad_block="false";
printf '\x'"${h}";
fi
# Case where we're inside of a substring that we want to extract
else
if [ "${d}" -ge 32 ] && [ "${d}" -le 127 ]; then
printf '\x'"${h}";
else
inside_bad_block="true";
echo
fi
fi
done
if [ "${inside_bad_block}" == "false" ]; then
echo
fi
0printf '\x00\x00\x00string1\xff\xff\xffstring2\x00\x00\x00string3\x00\x00\x00' > data.hex
0string1$ sh get_hex_substrings.sh data.hex
string1
string2
string3
0$ printf '%pre%0%pre%0%pre%0string1%pre%0%pre%0%pre%0string2%pre%0%pre%0%pre%0string3%pre%0%pre%0%pre%0' > file.dat
$ tr -s '%pre%0' '\n' < file.dat | cut -d$'\n' -f2
string1
0%pre%0string2%pre%0%pre%0%pre%0string3%pre%0%pre%0%pre%0' > file.dat
$ tr -s '%pre%0' '\n' < file.dat | cut -d$'\n' -f2
string1