Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
add alternative to command substitution for func return
Browse files Browse the repository at this point in the history
Faster space trim. Safe args. Capturing STDERR

faster space trim. Safe args. Capturing Stderr

nohup not required

double fork makes PID=1 the parent and thus automatically removed it from the current session group - and by this will not receive a SIGHUP on exit (which is what we want. Nohup is redundant in this case).

Update README.md

Update README.md
  • Loading branch information
txbm authored and SkyperTHC committed Jun 15, 2023
1 parent f14d877 commit 39b713c
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 6 deletions.
85 changes: 81 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ 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)
* [AFTERWORD](#afterword)

<!-- vim-markdown-toc -->
Expand Down Expand Up @@ -198,6 +199,16 @@ trim_string() {
}
```

```sh
trim_string_fast() {
local -
set -f
echo $1
}
```

The `local -` makes `$-` local so that `set -f` is only effective within this function.

**Example Usage:**

```shell
Expand All @@ -222,10 +233,10 @@ without leading/trailing white-space and with truncated spaces.
# shellcheck disable=SC2086,SC2048
trim_all() {
# Usage: trim_all " example string "
local -
set -f
set -- $*
printf '%s\n' "$*"
set +f
}
```

Expand Down Expand Up @@ -1892,9 +1903,10 @@ f()for i in "$@"; do echo "$i"; done
```shell
# One line
# Note: The 3rd statement may run when the 1st is true
# Note: The 3rd statement may run when the 1st is true and 2nd false
[[ $var == hello ]] && echo hi || echo bye
[[ $var == hello ]] && { echo hi; echo there; } || echo bye
# Note: The 3rd statement wont run when the 1st is true and 2nd false
[[ $var == hello ]] && { echo hi; echo there; :; } || echo bye
# Multi line (no else, single statement)
# Note: The exit status may not be the same as with an if statement
Expand Down Expand Up @@ -2163,12 +2175,77 @@ This will run the given command and keep it running, even after the terminal or
```sh
bkr() {
(nohup "$@" &>/dev/null &)
("$@" &>/dev/null &)
}
bkr ./some_script.sh # some_script.sh is now running in the background
```
## 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
```
## Making a string safe for passing as argument to another command
This is useful when executing a script on a remote system without copying the script (and when the remote shell is not Bash)
```sh
mk_safe_arg() {
# Escape all single-' with '"'"'
echo "${1//\'/\'\"\'\"\'}"
}
# A bash script for testing
cat >s.sh<<-'__EOF__'
#! /usr/bin/env bash
echo "Hello single-' and double-\" and '$USER' on '$HOSTNAME'"
__EOF__
# Load the script into the variable s
s="$(mk_safe_arg "$(<s.sh)")"
# Execute the script remotely without copying the script
ssh user@host "bash -c '$s'"
# Execute locally (for testing)
sh -c "bash -c '$s'"
```
## Capturing STDERR without capturing STDOUT.
The STDOUT passes through and STDERR is stored in `err`.
```sh
{ err="$( { echo 1>&2 "Hello-STDERR"; exit 123; } 2>&1 1>&3 3>&- )"; } 3>&1
echo "ret=$?, err=$err"
# ret=123, err=Hello-STDERR
```
The inner `{..}` writes to STDERR and exits with error code 123. The STDERR from the inner `{..}` is redirected to STDOUT with `2>&1`. The normal STDOUT is redirected to the newly created File Descriptor '3' with `1>&3 3>&-`. The outter `{..}` redirects File Descriptor '3' back to STDOUT with `3>&1`.
The variable `err` then contains the STDERR of the inner `{..}`.
## Block coomments
```sh
:<<-'###COMMENT-BLOCK'
This is a block comment in bash
Test $HOME $(id) `id` {} (:;)
###COMMENT-BLOCK
```
<!-- CHAPTER END -->
# AFTERWORD
Expand Down
20 changes: 18 additions & 2 deletions manuscript/chapter19.txt
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,27 @@ This will run the given command and keep it running, even after the terminal or
bkr() {
(nohup "$@" &>/dev/null &)
}
```

```shell
bkr ./some_script.sh # some_script.sh is now running in the background
```

## 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 -->

0 comments on commit 39b713c

Please sign in to comment.