Skip to content

Instantly share code, notes, and snippets.

@mknecht
Created March 20, 2016 08:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mknecht/293166f0338e517b50d7 to your computer and use it in GitHub Desktop.
Save mknecht/293166f0338e517b50d7 to your computer and use it in GitHub Desktop.
switched: A tool to recognize state changes in a command-line pipe.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import re
import sys
if sys.stdin.isatty():
print("""Outputs a line if the input changed.
Usage: {scriptname} [<switch regex>] [<custom message prefix>] [-print0]
Example:
ping google.com | {scriptname} 'time=\d+' 'Internet is ' | xargs -0 -n 1 notify-send
# Notifies you with a Desktop notification
# when pings start failing or succeeding.
echo -e "hello\n\n\nx" | ./switch.py "" "Empty region is "
# Outputs a message if for every switch in empty to non-empty lines
# and vice versa.
Makes only sense as part of a pipe, hence if stdin is connected to a TTY
this message will be output.
The start state is OFF.
switch regex: Determines if input changes (match vs non-match).
Default: non-whitespace.
custom message prefix: On flipping the message is output that
made the switch change. If this prefix is given, it will be output instead
and the word “ON” and “OFF” will be appended.
-print0: Terminates lines with 0, for usage with xargs. See `man find`.
""".format(scriptname=sys.argv[0]))
sys.exit(0)
regex = sys.argv[1] if len(sys.argv) > 1 and sys.argv[1] else r"\S+"
messageprefix = sys.argv[2] if len(sys.argv) > 2 else None
pattern = re.compile(regex)
# Possible clash with a message prefix or regex … but don't care.
end = "\x00" if '-print0' in sys.argv else os.linesep
def print_on_change(line, state):
message = line if not messageprefix else (messageprefix + state)
print(message, end=end)
sys.stdout.flush()
def main():
is_on = False
while True:
rawline = sys.stdin.readline()
if rawline == "":
sys.exit(0)
line = rawline.strip()
match = pattern.match(line)
if bool(match) ^ bool(is_on):
is_on = not is_on
print_on_change(line, "ON" if is_on else "OFF")
try:
main()
except KeyboardInterrupt:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment