Skip to content

Instantly share code, notes, and snippets.

@td-shi
Created June 24, 2024 12:35
Show Gist options
  • Save td-shi/350688467d9b7835cb337d2f30b2ca0a to your computer and use it in GitHub Desktop.
Save td-shi/350688467d9b7835cb337d2f30b2ca0a to your computer and use it in GitHub Desktop.
#!/bin/sh
# -*- coding:utf-8 posix -*-
# === Initialize shell environment =============================================
#set -u # Just stop undefined values.
#set -e # Just stop error.
#set -x # Debug running command.
umask 0022
export LC_ALL=C
export LANG=C
PATH="$(command -p getconf PATH 2>/dev/null)${PATH+:}${PATH-}"
case $PATH in (:*) PATH=${PATH#?};; esac
export PATH # or PATH="<add dir>${PATH+:}${PATH-}"
export UNIX_STD=2003 # to make HP-UX conform to POSIX
# === Define the functions for printing usage and error message ================
usage_and_exit(){
cat <<-"USAGE" 1>&2
# About
The uuidv7gen.sh generate UUIDv7. This script only handles the case where
rand_a and rand_b are random numbers.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | ver | rand_a |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# Usage
## Command
uidv7gen.sh [Options] [--msec <ms>] [-d <delimiter>]
```
$> uuidv7gen.sh
01904a37-df30-789e-8b43-e83a9718cc28
```
```
$> ./uuidv7gen.sh -d "_" | tr "abcdef" "ABCDEF"
01904A3B_B790_7A32_DC8E_5C5C7B12863C
```
```
$> i=0; while [ 5 -gt $i ] ; do i=$(( i + 1 )); ./uuidv7gen.sh --msec 178598740350$i; done
019fd525-0eed-74fd-c04a-1e529e726fec
019fd525-0eee-7519-8e1b-3e08ef286c33
019fd525-0eef-712a-e8e8-4788c5a537eb
019fd525-0ef0-7a41-de69-cc3363c7a516
019fd525-0ef1-7e31-d01e-1e55043e7a92
```
## Options
+ -h |--help |--version
- help.
+ --msec <ms>
- Generating at <ms>.
# Version
2024-06-25T23:10:00 0.01 [Latest](https://gist.github.com/search?q=user%3Atd-shi+filename%3A.sh+uuid)
# LICENSE
[CC0(Public domain)](https://creativecommons.org/publicdomain/zero/1.0/legalcode)
# Author
2024 TD
USAGE
exit 1
}
error_exit() {
${2+:} false && echo "${0##*/}: $2" 1>&2
exit "$1"
}
# === Initialize parameters ====================================================
TIME=0
DELI="-"
# === Confirm that the required commands exist =================================
if type hexdump >/dev/null 2>&1 ; then
genRandom () {
hexdump -n 16 -e '8/2 " %04x" "\n"' -v /dev/urandom | tr -d " "
}
elif type od >/dev/null 2>&1 ; then
genRandom () {
od -A n -t x2 -N 16 -v /dev/urandom | tr -d " "
}
else
error_exit 1 'require command "hexdump" or "od"'
fi
type od >/dev/null 2>&1 || error_exit 1 'require command od'
# === Print usage and exit if one of the help options is set ===================
case "$# ${1:-}" in
('1 -h'|'1 --help'|'1 --version') usage_and_exit;;
esac
# === Read options =============================================================
while :; do
case "${1:-}" in
(--|-)
break
;;
(--msec)
TIME=$(printf '%s' "${2:-}" | tr -Cd "0123456789")
shift 2
;;
(--delimiter|-d)
DELI=$(printf '%s' "${2:--}")
shift 2
;;
(--*|-*)
error_exit 1 'Invalid option'
;;
(*)
break
;;
esac
done
# === Require parameters check =================================================
# === Last parameter ===========================================================
# === Define funcitons =========================================================
unixTimeSec () {
set -- "$(date -u "+%Y-%m-%d %H:%M:%S")" "$1"
set -- "${1%% *}" "${1##* }" "$2"
set -- "${1%%-*}" "${1#*-}" "${2%%:*}" "${2#*:}" "$3"
set -- "$1" "${2%%-*}" "${2#*-}" "$3" "${4%%:*}" "${4#*:}" "$5"
set -- "${1}" "${2#0}" "${3#0}" "${4#0}" "${5#0}" "${6#0}" "$7"
[ "$2" -lt 3 ] && set -- $(($1 - 1)) $(($2 + 12)) "$3" "$4" "$5" "$6" "$7"
set -- $(( (365 * $1) + ($1 / 4) - ($1 / 100) + ($1 / 400))) $(( (306 * (1 + $2) / 10) - 428 )) "$3" "$4" "$5" "$6" "$7"
set -- $(( ($1 + $2 + $3 - 719163) * 86400 + $4 * 3600 + $5 * 60 + $6 )) "$7"
printf "%s%s" "$1" "$2"
}
decode2Hex () {
set -- "$1" "0" ""
while [ "$1" -gt 0 ] ; do
set -- "$(( $1 / 16))" "$(( $1 % 16 ))" "$3"
set -- "$1" "$2" "\\0$(( ($2>>3) + 6))$(($2 & 0x7))$3"
done
printf "$3" | tr ":;<=>?" "abcdef"
}
# === Main routine =============================================================
if [ "_" != "_${TIME}" ] && [ "${TIME}" -gt 0 ]; then
:
else
TIME=$(unixTimeSec "000")
fi
set -- "0000000000000$(decode2Hex "${TIME}")" "$(genRandom)"
set -- "${1#${1%????????????}}" "${2#${2%????????????????????}}" # 12, 20
set -- "${1%????}" "${1#????????}" "${2%??????????}" "${2#??????????}"
set -- "${1}" "${2}" "7${3%???????}" "${3#???}" "${3#????}" "${3#????????}${4%?????}${4#?????}"
set -- "${1}" "${2}" "${3}" "$(echo "${4%??????}" | tr "01234567" "89abcdef")" "${5%???}" "${6}"
printf "%s\n" "${1}${DELI}${2}${DELI}${3}${DELI}${4}${5}${DELI}${6}"
# === End shell script =========================================================
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment