add the --group argument
This commit is contained in:
parent
1b9ca96996
commit
49e8b76c2d
2 changed files with 64 additions and 21 deletions
38
README.md
38
README.md
|
|
@ -8,7 +8,7 @@ A command line tool that call the given command for each input line matching the
|
||||||
|
|
||||||
`paternoster` [-h]
|
`paternoster` [-h]
|
||||||
|
|
||||||
`paternoster` [-w] PATTERN COMMAND(S)
|
`paternoster` [-w] [-e] PATTERN COMMAND(S)
|
||||||
|
|
||||||
|
|
||||||
## DESCRIPTION
|
## DESCRIPTION
|
||||||
|
|
@ -25,20 +25,48 @@ silently ignored. If you ask for fewer commands, the last one will be
|
||||||
duplicated across remaining groups.
|
duplicated across remaining groups.
|
||||||
|
|
||||||
|
|
||||||
|
## OPTIONS
|
||||||
|
|
||||||
|
* `-h`, `--help`:
|
||||||
|
Show a help message and exit
|
||||||
|
|
||||||
|
* `-w`, `--nowait`:
|
||||||
|
Don't wait for the end of the current command before calling the next one.
|
||||||
|
|
||||||
|
* `-e`, `--end`:
|
||||||
|
Run commands at the end of the input stream.
|
||||||
|
|
||||||
|
* `-g`, `--group`:
|
||||||
|
Capture groups as arguments for the CMD, instead of running CMD for each group.
|
||||||
|
CMD must have as many formating placeholder as captured groups.
|
||||||
|
For example, if you capture 3 groups, you must put 3 formating placeholders in CMD:
|
||||||
|
`paternoster --group "^(.*):(.*):(.*)$" "echo '>>> 1:%s 2:%s 3:%s <<<'"`
|
||||||
|
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
||||||
* Make the speakers beep for every FIXME found in a source code:
|
* Make the speakers beep for every FIXME found in a source code:
|
||||||
`cat source.ext | paternoster "FIXME" "beep"
|
`cat paternoster.py | paternoster "FIXME" "beep"
|
||||||
|
|
||||||
* Play a sound for each error or warning on a compiler output (you must have the
|
* Play a sound for each error or warning on a compiler output (you must have the
|
||||||
corresponding wav files somewhere in you path):
|
corresponding sound files in you path):
|
||||||
`make 2>&1 | paternoster ".*(error|warning): .*$" "play %s.wav"`
|
`make 2>&1 | paternoster ".*(error|warning): .*$" "ogg123 %s.ogg"`
|
||||||
|
|
||||||
* Say out loud the error in a compiler output:
|
* Say out loud the error in a compiler output:
|
||||||
`make 2>&1 | paternoster ".*(error: .*)$" "espeak --punct=';{}()' '%s'"`
|
`make 2>&1 | paternoster ".*(error: .*)$" "espeak --punct=';{}()' '%s'"`
|
||||||
|
|
||||||
|
* Play a series of sounds corresponding to the sequence of errors and warning
|
||||||
|
at the end of a compilation:
|
||||||
|
`make 2>&1 | paternoster --end ".*(error|warning): .*" "ogg123 %.ogg"`
|
||||||
|
|
||||||
|
* Notify the desktop every time a user logs in:
|
||||||
|
`tail -n 2 -f /var/log/auth.log | paternoster ".*session opened for user ([^\s]+)\s*" "notify-send '%s login'"`
|
||||||
|
|
||||||
|
* Notify the desktop every time a user logs in or out:
|
||||||
|
`tail -n 2 -f /var/log/auth.log | paternoster --group ".*session (opened|closed) for user ([^\s]+)\s*" "notify-send '%s %s'"`
|
||||||
|
|
||||||
|
|
||||||
## CREDITS
|
## CREDITS
|
||||||
|
|
||||||
* Error sound by tcpp, licensed under CC-BY: http://www.freesound.org/people/tcpp/sounds/151309/
|
* Error sound by tcpp, licensed under CC-BY: http://www.freesound.org/people/tcpp/sounds/151309/
|
||||||
*
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ def run( cmd, text, nowait=False ):
|
||||||
# If there is a string formatting mark
|
# If there is a string formatting mark
|
||||||
try:
|
try:
|
||||||
# put the matching text in it
|
# put the matching text in it
|
||||||
behest = cmd % text
|
behest = cmd % tuple(text)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# else, do not
|
# else, do not
|
||||||
behest = cmd
|
behest = cmd
|
||||||
|
|
@ -35,7 +35,7 @@ def call( cmd, text, nowait=False, queue=None ):
|
||||||
run( cmd, text, nowait )
|
run( cmd, text, nowait )
|
||||||
|
|
||||||
|
|
||||||
def parse( text, pattern, cmd=[""], nowait=False, queue=None ):
|
def parse( text, pattern, cmd=[""], nowait=False, queue=None, capture_groups = False ):
|
||||||
|
|
||||||
regex = re.compile(pattern)
|
regex = re.compile(pattern)
|
||||||
for match in regex.finditer(text):
|
for match in regex.finditer(text):
|
||||||
|
|
@ -47,18 +47,29 @@ def parse( text, pattern, cmd=[""], nowait=False, queue=None ):
|
||||||
else:
|
else:
|
||||||
nb_groups = len(match.groups())
|
nb_groups = len(match.groups())
|
||||||
|
|
||||||
# Build a list of colors that match the number of grouped,
|
if capture_groups:
|
||||||
# If there is not enough commands, duplicate the last one.
|
# For each group index.
|
||||||
group_cmds = cmd + [cmd[-1]] * (nb_groups - len(cmd))
|
# Note that match.groups returns a tuple (thus being indexed in [0,n[),
|
||||||
|
# but that match.start(0) refers to the whole match, the groups being indexed in [1,n].
|
||||||
|
# Thus, we need to range in [1,n+1[.
|
||||||
|
texts = []
|
||||||
|
for group in range(1, nb_groups+1):
|
||||||
|
# If a group didn't match, there's nothing to do
|
||||||
|
if match.group(group) is not None:
|
||||||
|
texts.append( text[match.start(group):match.end(group)] )
|
||||||
|
|
||||||
# For each group index.
|
# Finally, call a single command with all the captured groups
|
||||||
# Note that match.groups returns a tuple (thus being indexed in [0,n[),
|
call( cmd[0], texts, nowait, queue )
|
||||||
# but that match.start(0) refers to the whole match, the groups being indexed in [1,n].
|
|
||||||
# Thus, we need to range in [1,n+1[.
|
else:
|
||||||
for group in range(1, nb_groups+1):
|
# Build a list of commands that match the number of groups,
|
||||||
# If a group didn't match, there's nothing to do
|
# If there is not enough commands, duplicate the last one.
|
||||||
if match.group(group) is not None:
|
group_cmds = cmd + [cmd[-1]] * (nb_groups - len(cmd))
|
||||||
call( group_cmds[group-1], text[match.start(group):match.end(group)], nowait, queue )
|
|
||||||
|
for group in range(1, nb_groups+1):
|
||||||
|
# If a group didn't match, there's nothing to do
|
||||||
|
if match.group(group) is not None:
|
||||||
|
call( group_cmds[group-1], text[match.start(group):match.end(group)], nowait, queue )
|
||||||
|
|
||||||
|
|
||||||
def write( text, stream = sys.stdout):
|
def write( text, stream = sys.stdout):
|
||||||
|
|
@ -77,7 +88,7 @@ def write( text, stream = sys.stdout):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def read_parse( stream_in, stream_out, pattern, cmd, nowait = False, at_end = False ):
|
def read_parse( stream_in, stream_out, pattern, cmd, nowait = False, at_end = False, capture_groups = False ):
|
||||||
"""
|
"""
|
||||||
Read the given file-like object as a non-blocking stream
|
Read the given file-like object as a non-blocking stream
|
||||||
and call the function on each item (line),
|
and call the function on each item (line),
|
||||||
|
|
@ -107,7 +118,7 @@ def read_parse( stream_in, stream_out, pattern, cmd, nowait = False, at_end = Fa
|
||||||
# Write the line being processed
|
# Write the line being processed
|
||||||
write( item, stream_out )
|
write( item, stream_out )
|
||||||
# Then do something
|
# Then do something
|
||||||
parse(item, pattern, cmd, nowait, events)
|
parse(item, pattern, cmd, nowait, events, capture_groups)
|
||||||
|
|
||||||
if at_end:
|
if at_end:
|
||||||
while events.not_empty:
|
while events.not_empty:
|
||||||
|
|
@ -140,7 +151,11 @@ if __name__ == "__main__":
|
||||||
parser.add_argument("-e", "--end", action="store_true",
|
parser.add_argument("-e", "--end", action="store_true",
|
||||||
help="Run commands at the end of the input stream.")
|
help="Run commands at the end of the input stream.")
|
||||||
|
|
||||||
|
parser.add_argument("-g", "--groups", action="store_true",
|
||||||
|
help="Capture groups as arguments for the CMD, instead of running CMD for each group.\
|
||||||
|
CMD must have as many formating placeholder as captured groups.")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
read_parse( sys.stdin, sys.stdout, args.pattern[0], args.commands, args.no_wait, args.end )
|
read_parse( sys.stdin, sys.stdout, args.pattern[0], args.commands, args.no_wait, args.end, args.groups )
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue