1: #!/usr/bin/rexx
2: --
3: -- A Generalized Rexx Filter that can be used in a pipe
4: --
5: -- Usage: rexx filter.rex builtin-or-external-function-name(arg1, arg2, ...)
6: -- or: rexx filter.rex < inputfile
7: -- or: rexx filter.rex (boolean expression)
8: --
9: -- Note 1:
10: --
11: -- rexx (to invoke filter.rex) may or may not be required to get
12: -- the redirection and piping working, dependent on the operating
13: -- system and the REXX implementation and/or installation setup.
14: --
15: -- External functions can have a simple structure, for instance:
16: --
17: -- rexx filter.rex "cut.rex(!line,10:5)" or filter.rex "cut(!line,10:5)"
18: --
19: -- parse arg line,poslen
20: -- parse var poslen pos ':' length .
21: -- /* possibly more logic, but return value should be a (modified)
22: -- line or a boolean if the function is called as an expression */
23: -- return delstr(line,pos,length)
24: --
25: -- Argument(s)/Option(s) or even all of the filter have to be quoted generally.
26: -- On Windows: It's best to use '"' for all of the filtere and "'" for arguments.
27: -- On *n?x: It's best to use "'" for all of the filter and '"' for arguments.
28: -- On *n?x: Redirection (< and > or >> ) doesn't seem to work all of the time.
29: --
30: -- Pipe variables:
31: --
32: -- The input line from the pipe is represented by '!line'.
33: -- The running line count is represented by '!count'
34: -- The total nr of lines is respresented by '!lines'
35: -- Using '!lines' in the filter implies buffering the input stream before
36: -- any output is passed on to the next pipe stage.
37: --
38: -- Example 1: rexx filter.rex changestr(needle,!line,newneedle)
39: --
40: -- Example 2: rexx filter.rex strip(!line,'L','>')
41: --
42: -- Example 3: rexx filter.rex < somefile.txt - just echoes the input
43: --
44: -- Example 4: rexx filter.rex (pos('>',!line)>0) - a boolean expression
45: --
46: -- Example 5: rexx filter.rex "(!count>10)" - skips first 10 lines of input
47: --
48: -- Example 6: rexx filter.rex "(!count>!lines-10)" - shows last 10 lines of input
49: --
50: -- rexx filter.rex 0) -- a buffered stage can delay the input stream
72: nop
73: end
74: !buffered = (pos('!lines',!filter)>0)
75: if (!buffered) then do -- buffer input stream on standard queue
76: do !lines=1 by 1 while (lines()>0)
77: queue linein()
78: end
79: !lines = queued()
80: !queued = !lines
81: if (!queued>0) then do -- prefetch the 1st line queue
82: parse pull !line
83: end
84: end
85: else do
86: !queued = lines()
87: if (!queued>0) then do -- prefetch the 1st line from stdin
88: !line = linein()
89: end
90: end
91: do !count=1 by 1 while (!queued>0)
92: if (!filter = '') then do -- no filter just echoes the input
93: !out = !line
94: end
95: else do
96: if (substr(!filter,1,1)='(') then do
97: drop !out -- to verify !out is a var later on
98: interpret '!test =' !filter -- apply the test
99: if (!test) then do -- if test yields .true it goes out
100: !out = !line
101: end
102: end
103: else do -- apply the filter
104: interpret '!out =' !filter
105: end
106: end
107: if (var("!out")) then do -- only write if we have something
108: call lineout ,!out
109: end
110: if (!buffered) then do -- if buffered, next line from queue
111: !queued = queued()
112: if (!queued>0) then do
113: parse pull !line
114: end
115: end
116: else do -- not buffered, next line from stdin
117: !queued = lines()
118: if (!queued>0) then do
119: !line = linein()
120: end
121: end
122: end
123: exit