Skip to content

Instantly share code, notes, and snippets.

@ildar-shaimordanov
Last active November 10, 2023 18:34
Show Gist options
  • Save ildar-shaimordanov/d39b69f20c0d7c28b4b9ff14c8645c9b to your computer and use it in GitHub Desktop.
Save ildar-shaimordanov/d39b69f20c0d7c28b4b9ff14c8645c9b to your computer and use it in GitHub Desktop.

Once I decided weirdly to combine two commands into a single one with possibility to keep the command line options of the both commands. It was assumed the following:

# original and simple usage
command1 options1 | command2 options2

# modified and weird one
super_command options1 -- options2

Bash supports string and array indexing, whereas a POSIX shell does not. With bash we can use something similar to (assuming that the double dash "--" is on the sixth position):

command1 "${@:1:5}" | command2 "${@:7}"

I found a workaround way for POSIX. It has been tested under BusyBox which provides the restricted and POSIX-compliant ash.

Usage (see the complete proof of the concept below)

minus_minus_position "$@"

eval log_left $( reparse_left_arguments "$@" ) \
| eval log_right $( reparse_right_arguments "$@" )
#!/bin/sh
# =========================================================================
. ./minus-minus-position.sh
# =========================================================================
demo() {
s="$1"
shift
printf "$s : %s\n" "$@" >&2
}
# =========================================================================
minus_minus_position "$@"
eval demo "LEFT" $( reparse_left_arguments "$@" ) \
| eval demo "RIGHT" $( reparse_right_arguments "$@" )
# =========================================================================
# EOF
#!/bin/sh
# =========================================================================
. ./minus-minus-position.sh
# =========================================================================
demo() {
s="$1"
shift
printf "$s : %s\n" "$@" >&2
}
# =========================================================================
minus_minus_position "$@"
(
eval set -- $( reparse_left_arguments "$@" )
demo "LEFT" "$@"
) | (
eval set -- $( reparse_right_arguments "$@" )
demo "RIGHT" "$@"
)
# =========================================================================
# EOF
# =========================================================================
#
# POSIX-compliant way for string and array indexing
# A partial case implementation for the double minus
#
# =========================================================================
# Look up the position of the "--" option and set the MINUS_MINUS_POSITION
# variable to the position of "--", if it presents in the command line.
# Set to $#+1, otherwise.
minus_minus_position() {
MINUS_MINUS_POSITION=1
while [ $# -gt 0 ]
do
[ "$1" = "--" ] && return
shift
MINUS_MINUS_POSITION=$(( MINUS_MINUS_POSITION+1 ))
done
}
# Prepare arguments for setting them in "eval ..."
reparse_arguments() {
[ $# -gt 0 ] || return
printf '%s\n' "$@" \
| awk -v apos="'" -v bsol="\\\\" -v ORS=" " \
-v side="$MINUS_MINUS_SIDE" \
-v mmpos="$MINUS_MINUS_POSITION" '
side < 0 && NR == mmpos { exit }
side > 0 && NR <= mmpos { next }
{ gsub(apos, apos bsol apos apos); print apos $0 apos }'
}
# Prepare arguments for setting them in "eval ..." for the left command
# (that is supposed to be executed in the left side of the pipe).
reparse_left_arguments() {
MINUS_MINUS_SIDE=-1
reparse_arguments "$@"
}
# Prepare arguments for setting them in "eval ..." for the right command
# (that is supposed to be executed in the right side of the pipe).
reparse_right_arguments() {
MINUS_MINUS_SIDE=+1
reparse_arguments "$@"
}
# =========================================================================
# EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment