Skip to content

Instantly share code, notes, and snippets.

@alissonsales
Last active August 7, 2018 03:54
Show Gist options
  • Save alissonsales/7c7d00e7bd8ae3802e0c9a4ef1d75171 to your computer and use it in GitHub Desktop.
Save alissonsales/7c7d00e7bd8ae3802e0c9a4ef1d75171 to your computer and use it in GitHub Desktop.
Redis protocol in awk
awk '{ print "*" NF "\r"; for(i = 1; i <= NF; i++) { print "$" length($i) "\r\n" $i "\r" } }'
SADD my_set 1
SADD my_set 2
SADD my_set 3
SADD my_set 4
SADD my_set 5
SADD my_set 6
SADD my_set 7
SADD my_set 8
SADD my_set 9
SADD my_set 10
awk '{ print "*" NF "\r"; for(i = 1; i <= NF; i++) { print "$" length($i) "\r\n" $i "\r" } }' sample | redis-cli --pipe

If redis is running on docker use:

awk '{ print "*" NF "\r"; for(i = 1; i <= NF; i++) { print "$" length($i) "\r\n" $i "\r" } }' sample | docker exec -i redis redis-cli --pipe

Gotchas

This is based on the ruby snippet described here that uses ruby String.bytesize which is not exactly the same of awk's string length, so use this at your own risk.

For my usage this worked like a charm.

The version below supports bytesize using wc -c, but it feels bad to perform a system call for every argument and it's also very slow.

awk '{ print "*" NF "\r"; for(i = 1; i <= NF; i++) { system("printf " $i "| wc -c | sed -e \"s/ *//\" -e \"s/^/$/\" -e \"s/$/\r/\""); print $i "\r" } }'

On Mac OS this awk's length() seems to count the actual bytesize of a string.

$ echo -n 'Jose' | awk '{ print length($1) }'
4
$ echo -n 'José' | awk '{ print length($1) }'
5
@edgurgel
Copy link

This is awesome

@alissonsales
Copy link
Author

alissonsales commented Aug 7, 2018

If you have spaces on the last argument you can use something like this: awk '{ argsize = 4; pos = 0; print "*" argsize "\r"; for(i = 1; i <= argsize; i++) { arg = (i == argsize) ? substr($0, pos + 1) : $i; print "$" length(arg) "\r\n" arg "\r"; pos += length(arg) + 1 } }' where 4 is the number of arguments.

This is the case for a command such as: HSET my_set key {"key":"string with spaces"}

Unfortunately this only works for files where all the commands have the same number of arguments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment