commit 4c2a91533d1ba44ea50e1e870fefc03723dec3ba Author: yafox Date: Tue Nov 24 20:54:17 2020 +0000 initial commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bd8c239 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright 2020 "yafox" + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README b/README new file mode 100644 index 0000000..05fe129 --- /dev/null +++ b/README @@ -0,0 +1,36 @@ +shsort +====== + +a recursive quicksort in pure posix shell script using any arbitrary function +or command capable of parsing a comparison expression and outputing "yes" or +"no." (e.g., anything that takes a string in the form of "1 > 3" as a command +line argument and echoes "no" and takes "1 < 3" and echoes "yes".) + +34 SLOC. + +usage: shsort [-r] [] + +shsort expects a newline delimited list of elements to sort. the list may be +passed via stdin in or on the command line as the argument. + +the comparator command is used as-is and may be a string including flags. + +for example: + + $ printf "2.9\n1.2\n3.4\n2.1\n2.1-rc0\n2.12" | shsort "vercmp -f default" + 3.4 + 2.12 + 2.9 + 2.1 + 2.1-rc0 + 1.2 + +`-r` reverses the sort order: + + $ printf "2.9\n1.2\n3.4\n2.1\n2.1-rc0\n2.12" | shsort -r "vercmp -f default" + 1.2 + 2.1-rc0 + 2.1 + 2.9 + 2.12 + 3.4 diff --git a/makefile b/makefile new file mode 100644 index 0000000..814d6bf --- /dev/null +++ b/makefile @@ -0,0 +1,9 @@ +SRCDIR = $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) +PREFIX ?= /usr +DESTDIR ?= $(PREFIX)/bin + +install: + cp -a $(SRCDIR)/shsort.sh $(DESTDIR)/shsort + +uninstall: + rm $(DESTDIR)/shsort diff --git a/shsort.sh b/shsort.sh new file mode 100755 index 0000000..811f443 --- /dev/null +++ b/shsort.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +set -e + +usage() { echo "usage: shsort [-r] []" >&2 && exit 0; } + +[ "$1" ] || usage + +[ "$1" != "-r" ] || { rev="yes" && shift; } + +cmpfn="$1" +shift + +quicksort() { + len="$(printf "$@\n" | wc -l)" + [ "$len" -gt 1 ] || { echo "$@" && return 0; } + + pvtidx="$(expr $len / 2)" + pvt="$(printf "$@\n" | head -n$pvtidx | tail -n1)" + + parted="$(printf "$@\n" | while read elem; do + { [ "$elem" ] && [ "$elem" != "$pvt" ]; } || continue + [ "$($cmpfn "$elem < $pvt")" = "yes" ] \ + && printf "<\t$elem\n" \ + || printf ">\t$elem\n" + done)" + lesser="$(printf "$parted\n" | grep "^<" | cut -f2)" + greater="$(printf "$parted\n" | grep "^>" | cut -f2)" + + if [ "$rev" ]; then + printf "%s\n%s\n%s\n" "$(quicksort "$lesser")" "$pvt" "$(quicksort "$greater")" + else + printf "%s\n%s\n%s\n" "$(quicksort "$greater")" "$pvt" "$(quicksort "$lesser")" + fi +} + +if [ "$@" ]; then + elems="$@" +else + while read input; do + elems="$elems$input\n" + done +fi +[ "$elems" ] || usage + +quicksort "$elems" | sed '/^$/d' diff --git a/sloc.sh b/sloc.sh new file mode 100755 index 0000000..0129927 --- /dev/null +++ b/sloc.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# strip all trailing whitespace, then all leading whitespace, then all lines +# starting with '#', then all empty lines. then count the remaining lines. +sed 's/[[:space:]]*$//g; s/^[[:space:]]*//g; s/^#.*$//g; /^$/d' shsort.sh \ +| wc -l - \ +| cut -d' ' -f1 + +# note that this script's ELOC is NOT included in the count.