commit b131e501e0f6ecb2914b3f82227f8ff88d6c0855
parent afbd66b19f91bd616c10a489a76c501f4f0390c4
Author: Jacob R. Edwards <n/a>
Date: Wed, 28 Dec 2022 13:39:17 -0800
Add sr script
This script maintains a table of records (currently always lines)
from files. If the given name is prefixed with a plus ('+') it's
records are added to the table, if it's prefixed with minus ('-'),
records found in it are removed from the table.
At the end, all the records are printed out in the order they were
added to the table.
Diffstat:
| A | local/bin/bin/sr | | | 86 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 86 insertions(+), 0 deletions(-)
diff --git a/local/bin/bin/sr b/local/bin/bin/sr
@@ -0,0 +1,86 @@
+#!/bin/sh
+# Copyright 2022 Jacob R. Edwards
+# sr -- select records
+#
+# This script maintains a table of records (currently always lines)
+# from files. If the given name is prefixed with a plus ('+') it's
+# records are added to the table, if it's prefixed with minus ('-'),
+# records found in it are removed from the table.
+#
+# At the end, all the records are printed out in the order they were
+# added to the table. (If a record is already in the table, it is not
+# added again, so if the same record was obtained from both 'a' and
+# 'b' and it wasn't removed in between, it's position is depended
+# solely upon 'a'.)
+
+
+awk 'function die(msg)
+{
+ status = msg
+ exit 1
+}
+
+function usage(msg)
+{
+ die(sprintf("%s\n%s", msg, "usage: sr (+|-)file [...]"));
+}
+
+function addx(x)
+{
+ if (! (x in t)) {
+ t[x] = count++;
+ }
+}
+
+function subx(x)
+{
+ if (x in t)
+ delete t[x];
+}
+
+function dofile(expr, _, op, file, n, line)
+{
+ op = substr(expr, 1, 1);
+ if (!match(op, "^[+-]$"))
+ usage(op ": Invalid operator");
+
+ file = substr(expr, 2);
+ if (!file)
+ file = "/dev/stdin"
+
+ while ((n = getline line < file) > 0)
+ op == "+" ? addx(line) : subx(line);
+ close(file)
+ if (n < 0)
+ die(file ": Unable to read file")
+}
+
+BEGIN {
+ keeporder = 1
+
+ if (ARGC == 1)
+ ARGV[ARGC++] = "+"
+
+ for (i = 1; i < ARGC; ++i)
+ dofile(ARGV[i]);
+
+ if (!keeporder) {
+ for (i in t)
+ print(i)
+ exit 0
+ }
+
+ for (i in t)
+ rt[t[i]] = i
+ for (i = 0; i < count; ++i)
+ if (i in rt)
+ print rt[i];
+ exit 0
+}
+
+END {
+ if (status) {
+ print "error: " status > "/dev/stderr"
+ exit 1
+ }
+}' "$@"