Compare commits

...

5 Commits

Author SHA1 Message Date
Ross Smith II a47c337d80
Merge c601895832 into 8c19d0b482 2023-11-26 07:38:13 -08:00
Ross Smith II c601895832
Merge branch 'master' into rasa/add_hd 2023-11-26 07:38:04 -08:00
dylan 8c19d0b482
Merge pull request #106 from pipefail/master
add namerefs to avoid command substitution subproc for function output assignment
2020-10-21 18:39:38 +03:00
Peter M. Elias 2549b02e6f add alternative to command substitution for func return 2020-10-20 07:33:12 -05:00
Ross Smith II dc9f422f2c
Add hd alternative 2020-02-19 13:06:51 -08:00
3 changed files with 152 additions and 1 deletions

View File

@ -161,6 +161,8 @@ See something incorrectly described, buggy or outright wrong? Open an issue or s
* [Bypass shell aliases](#bypass-shell-aliases)
* [Bypass shell functions](#bypass-shell-functions)
* [Run a command in the background](#run-a-command-in-the-background)
* [Capture function return without command substitution](#capture-the-return-value-of-a-function-without-command-substitution)
* [Display a hexidecimal dump](#Display-a-hexidecimal-dump)
* [AFTERWORD](#afterword)
<!-- vim-markdown-toc -->
@ -2169,6 +2171,75 @@ bkr() {
bkr ./some_script.sh # some_script.sh is now running in the background
```
## Display a hexidecimal dump
This is an alternative to `hd` or `hexdump -C`.
**Example Function:**
```sh
hd() {
if (($#)); then
hd <"$1"
return
fi
local IFS='' # disables interpretation of \t, \n and space
local LANG=C # allows characters > 0x7F
local bytes=0 char chars=''
declare -i bytes
printf '%08x ' 0
while read -s -d '' -r -n 1 char; do # -d '' allows newlines, -r allows \
printf '%02x ' "'$char" # see https://pubs.opengroup.org/onlinepubs/009695399/utilities/printf.html
[[ "$char" =~ [[:print:]] ]] || char='.' # display non-printables as a dot
chars+=$char
((++bytes % 8)) && continue
printf ' '
((bytes % 16)) && continue
printf '|%s|\n%08x ' "$chars" "$bytes"
chars=''
done
if [[ "$chars" ]]; then
len=${#chars}
((len > 7 && len--, len += (16 - (bytes % 16)) * 3 + 4))
printf "%${len}s\n%08x " "|$chars|" "$bytes"
fi
printf '\n'
}
```
**Example Usage:**
```shell
$ echo -e '\e[5mHello,\tWorld\e[m\0' | hd
00000000 1b 5b 35 6d 48 65 6c 6c 6f 2c 09 57 6f 72 6c 64 |.[5mHello,.World|
00000010 1b 5b 6d 00 0a |.[m..|
00000015
$ echo -e '\e[5mHello,\tWorld\e[m\0' >test_file
$ hd test_file
00000000 1b 5b 35 6d 48 65 6c 6c 6f 2c 09 57 6f 72 6c 64 |.[5mHello,.World|
00000010 1b 5b 6d 00 0a |.[m..|
00000015
## Capture the return value of a function without command substitution
**CAVEAT:** Requires `bash` 4+
This uses local namerefs to avoid using `var=$(some_func)` style command substitution for function output capture.
```sh
to_upper() {
local -n ptr=${1}
ptr=${ptr^^}
}
foo="bar"
to_upper foo
printf "%s\n" "${foo}" # BAR
```
<!-- CHAPTER END -->
# AFTERWORD

View File

@ -219,10 +219,78 @@ This will run the given command and keep it running, even after the terminal or
bkr() {
(nohup "$@" &>/dev/null &)
}
bkr ./some_script.sh # some_script.sh is now running in the background
```
## Display a hexidecimal dump
This is an alternative to `hd` or `hexdump -C`.
**Example Function:**
```sh
hd() {
if (($#)); then
hd <"$1"
return
fi
local IFS='' # disables interpretation of \t, \n and space
local LANG=C # allows characters > 0x7F
local char chars=''
declare -i bytes=0
printf '%08x ' 0
while read -s -d '' -r -n 1 char; do # -d '' allows newlines, -r allows \
printf '%02x ' "'$char" # see https://pubs.opengroup.org/onlinepubs/009695399/utilities/printf.html
[[ "$char" =~ [[:print:]] ]] || char='.' # display non-printables as a dot
chars+="$char"
((++bytes % 8)) && continue
printf ' '
((bytes % 16)) && continue
printf '|%s|\n%08x ' "$chars" "$bytes"
chars=''
done
if [[ "$chars" ]]; then
len=${#chars}
((len > 7 && len--, len += (16 - (bytes % 16)) * 3 + 4))
printf "%${len}s\n%08x " "|$chars|" "$bytes"
fi
printf '\n'
}
```
**Example Usage:**
```shell
bkr ./some_script.sh # some_script.sh is now running in the background
$ echo -e '\e[5mHello,\tWorld\e[m\0' | hd
00000000 1b 5b 35 6d 48 65 6c 6c 6f 2c 09 57 6f 72 6c 64 |.[5mHello,.World|
00000010 1b 5b 6d 00 0a |.[m..|
00000015
$ echo -e '\e[5mHello,\tWorld\e[m\0' >test_file
$ hd test_file
00000000 1b 5b 35 6d 48 65 6c 6c 6f 2c 09 57 6f 72 6c 64 |.[5mHello,.World|
00000010 1b 5b 6d 00 0a |.[m..|
00000015
```
## Capture the return value of a function without command substitution
**CAVEAT:** Requires `bash` 4+
This uses local namerefs to avoid using `var=$(some_func)` style command substitution for function output capture.
```sh
to_upper() {
local -n ptr=${1}
ptr=${ptr^^}
}
foo="bar"
to_upper foo
printf "%s\n" "${foo}" # BAR
```
<!-- CHAPTER END -->

12
test.sh
View File

@ -205,6 +205,18 @@ test_split() {
assert_equals "${result[*]}" "hello world my name is john"
}
test_hd() {
result="$(echo -e '\e[5mHello,\tWorld\e[m\0' | hd)"
expects=$'00000000 1b 5b 35 6d 48 65 6c 6c 6f 2c 09 57 6f 72 6c 64 |.[5mHello,.World|\n'
expects+=$'00000010 1b 5b 6d 00 0a |.[m..|\n'
expects+=$'00000015 '
assert_equals "$result" "$expects"
echo -e '\e[5mHello,\tWorld\e[m\0' > test_file
result="$(hd test_file)"
assert_equals "${result}" "$expects"
}
assert_equals() {
if [[ "$1" == "$2" ]]; then
((pass+=1))