Home > Blockchain >  How can I interpret a string that contains decimal escape sequences?
How can I interpret a string that contains decimal escape sequences?

Time:09-30

I'm trying to parse the "parsable" ouput of the avahi-browse command for use in a shell script. e.g.

for i in $(avahi-browse -afkpt | awk -F';' '{print $4}') ; do <do something with $i> ; done

The output looks like:

 ;br.vlan150;IPv4;Sonos-7828CAC5D944\064Bedroom;_sonos._tcp;local

I am particularly interested in the value of the 4th field, which is a "service name".

With the -p|--parsable flag, avahi-browse escapes the "service name" values.

For example 7828CAC5D944\064Bedroom, where \064 is a zero-padded decimal representation of the ASCII character '@'.

I just want 7828CAC5D944@Bedroom so I can, for example, use it as an argument to another command.

I can't quite figure out how to do this inside the shell.

I tried using printf, but that only seems to interpret octal escape sequences. e.g.:

# \064 is interpreted as 4
$ printf '%b\n' '7828CAC5D944\064Bedroom'
7828CAC5D9444Bedroom

How can I parse these values, converting any of the decimal escape sequences to their corresponding ASCII characters?

CodePudding user response:

Assumptions:

  • there's a reason the -p flag cannot be removed (will removing -p generate a @ instead of \064?)
  • the 4th field is to be further processed by stripping off all text up to and including a hyphen (-)
  • \064 is the only escaped decimal value we need to worry about (for now)

Since OP is already calling awk to process the raw data I propose we do the rest of the processing in the same awk call.

One awk idea:

awk -F';' '
{ n=split($4,arr,"-")         # split field #4 based on a hyphen delimiter
  gsub(/\\064/,"@",arr[n])    # perform the string replacement in the last arr[] entry
  print arr[n]                # print the newly modified string
}'

# or as a one-liner:

awk -F';' '{n=split($4,arr,"-");gsub(/\\064/,"@",arr[n]);print arr[n]}'

Simulating the avahi-browse call feeding into awk:

echo ' ;br.vlan150;IPv4;Sonos-7828CAC5D944\064Bedroom;_sonos._tcp;local' | 
awk -F';' '{n=split($4,arr,"-");gsub(/\\064/,"@",arr[n]);print arr[n]}'

This generates:

7828CAC5D944@Bedroom

And for the main piece of code I'd probably opt for a while loop, especially if there's a chance the avahi-browse/awk process could generate data with white space:

while read -r i
do
    <do something with $i> 
done < <(avahi-browse -afkpt | awk -F';' '{n=split($4,arr,"-");gsub(/\\064/,"@",arr[n]);print arr[n]}') 

CodePudding user response:

Using perl to do the conversion:

$ perl -pe 's/\\(\d )/chr $1/ge' <<<"7828CAC5D944\064Bedroom"
7828CAC5D944@Bedroom

As part of your larger script, completely replacing awk:

while read -r i; do
    # do something with i
done < <(avahi-browse -afkpt | perl -F';' -lane 'print $F[3] =~ s/\\(\d )/chr $1/ger')
  • Related