#!/usr/bin/rexx
--
-- A Generalized Rexx Filter that can be used in a pipe
--
-- Usage: rexx filter.rex builtin-or-external-function-name(arg1, arg2, ...)
-- or: rexx filter.rex < inputfile
-- or: rexx filter.rex (boolean expression)
--
-- Note 1:
--
-- rexx (to invoke filter.rex) may or may not be required to get
-- the redirection and piping working, dependent on the operating
-- system and the REXX implementation and/or installation setup.
--
-- External functions can have a simple structure, for instance:
--
-- rexx filter.rex "cut.rex(!line,10:5)" or filter.rex "cut(!line,10:5)"
--
-- parse arg line,poslen
-- parse var poslen pos ':' length .
-- /* possibly more logic, but return value should be a (modified)
-- line or a boolean if the function is called as an expression */
-- return delstr(line,pos,length)
--
-- Argument(s)/Option(s) or even all of the filter have to be quoted generally.
-- On Windows: It's best to use '"' for all of the filtere and "'" for arguments.
-- On *n?x: It's best to use "'" for all of the filter and '"' for arguments.
-- On *n?x: Redirection (< and > or >> ) doesn't seem to work all of the time.
--
-- Pipe variables:
--
-- The input line from the pipe is represented by '!line'.
-- The running line count is represented by '!count'
-- The total nr of lines is respresented by '!lines'
-- Using '!lines' in the filter implies buffering the input stream before
-- any output is passed on to the next pipe stage.
--
-- Example 1: rexx filter.rex changestr(needle,!line,newneedle)
--
-- Example 2: rexx filter.rex strip(!line,'L','>')
--
-- Example 3: rexx filter.rex < somefile.txt - just echoes the input
--
-- Example 4: rexx filter.rex (pos('>',!line)>0) - a boolean expression
--
-- Example 5: rexx filter.rex "(!count>10)" - skips first 10 lines of input
--
-- Example 6: rexx filter.rex "(!count>!lines-10)" - shows last 10 lines of input
--
-- rexx filter.rex <filter.rex | ,
-- rexx filter.rex (pos('-',!line)=1) | ,
-- rexx filter.rex strip(!line,'L','-')
--
-- will first read and echo filter.rex,
-- then output only input lines that start with '-',
-- then strip leading comment identifier '--'.
--
-- No copyright, no license, no guarantees, use at your own risk.
--
-- And you just read the result of the pipe above.
--
parse source . . me
parse arg !filter
do (!filter='?' | !filter='-?' | !filter='/?' | !filter='h' | !filter='-h' | !filter='/h' | !filter='--help')
pipe = 'rexx "'me'"<"'me'" | rexx "'me'" (pos(''-'',!line)=1) | rexx "'me'" strip(!line,''L'',''-'')'
pipe
exit
end
!filter = strip(strip(strip(!filter,'B',' '),'B',"'"),'B','"') -- strip spaces and quotes
do until (lines()>0) -- a buffered stage can delay the input stream
nop
end
!buffered = (pos('!lines',!filter)>0)
if (!buffered) then do -- buffer input stream on standard queue
do !lines=1 by 1 while (lines()>0)
queue linein()
end
!lines = queued()
!queued = !lines
if (!queued>0) then do -- prefetch the 1st line queue
parse pull !line
end
end
else do
!queued = lines()
if (!queued>0) then do -- prefetch the 1st line from stdin
!line = linein()
end)
end
do !count=1 by 1 while (!queued>0)
if (!filter = '') then do -- no filter just echoes the input
!out = !line
end
else do
if (substr(!filter,1,1)='(') then do
drop !out -- to verify !out is a var later on
interpret '!test =' !filter -- apply the test
if (!test) then do -- if test yields .true it goes out
!out = !line
end
end
else do -- apply the filter
interpret '!out =' !filter
end
end
if (var("!out")) then do -- only write if we have something
call lineout ,!out
end
if (!buffered) then do -- if buffered, next line from queue
!queued = queued()
if (!queued>0) then do
parse pull !line
end
end
else do -- not buffered, next line from stdin
!queued = lines()
if (!queued>0) then do
!line = linein()
end
end
end
exit