+# Usage: cmd_i <cmd> ... <file>
+#
+# Run <cmd> with all arguments (including the last file) and write the result
+# to the temporary file <file>.tmp and then rename that file to <file>. This
+# can't be done in-place (e.g. cmd <file >file) because it truncates the file.
+cmd_i() {
+ # Get last argument.
+ last=
+ for x; do
+ last="$x"
+ done
+
+ "$@" >"$last".tmp
+ mv "$last".tmp "$last"
+}
+
+# Usage: sed_i ... <file>
+#
+# sed -i is not portable due to different implementations. See cmd_i.
+sed_i() {
+ cmd_i sed "$@"
+}
+grep_i() {
+ cmd_i grep "$@"
+}
+
+# Usage: perl_line_filter <cmd> ...
+#
+# Run the perl command cmd on each line before printing it.
+perl_line_filter() {
+ cmd="$1"
+ shift
+
+ # Can't use -pe because it uses <> which treats the arguments as files.
+ perl -e "use strict; use warnings; while (<STDIN>) { $cmd; print; }" "$@"
+}
+
+# Usage: simple_cpp <FIRST> <SECOND> .. -- <replacement-for-first> ...
+#
+# Replaces each FIRST (on word boundaries) with <replacement-for-first> like a
+# simple cpp replacement.
+simple_cpp() {
+ cmd='my $i = 0;'
+
+ for x; do
+ shift
+
+ if test x"$x" = x--; then
+ break
+ fi
+
+ cmd="$cmd s/\\b$x\\b/\$ARGV[\$i]/g; \$i++;"
+ done
+
+ perl_line_filter "$cmd" -- "$@"
+}
+