Skip to main content
added 812 characters in body
Source Link
Kaz
  • 8.9k
  • 2
  • 31
  • 52

TXR solution, on the command line:

 $ txr -c '@(maybe) @(skip) @(trailer) @/pattern/ @(end) @(repeat) @line @(do (put-line line)) @(end)' - 

Example: lines in which pattern doesn't occur. Code abbreviated:

 $ txr -c '@(maybe) [...]' - a b c d Ctrl-DEnter a b c d 

When pattern occurs:

$ txr -c '@(maybe) [...] @(end)' - a b c pattern pattern x x y y z z Ctrl-DEnter 

As you can see, once pattern occurs, the lines start being echoed from then on.

The logic is very simple: material enclosed in @(maybe)...@(end) is optionally matched. There we have a @(skip) which skips any number of lines, followed by a @(trailer) which means "match the following as a trailing context (do not consume it)". (This feature and its name is inspired by the slash trailing contexts in Lex.) If we take out @(trailer) then the line which matches the pattern is excluded from the output.

Of course @/pattern/ is a regex. It is implicitly anchored: it must match the whole line. So to match a line which contains abc we would use @/.*abc.*/ or @(skip)abc@(skip).

In the case when the pattern doesn't occur, the skip inside maybe scans the entire input, and eventually fails. maybe catches this failure and sweeps it under the rug, producing a success. The material which follows the maybe is then matched, against the original input on which the interior of maybe failed (i.e. start of the stream).

At the end we we have an repetitive matching structure, @(repeat), which contains an output side effect.

A different TXR solution which uses the @(data ...) directive to capture the current data cursor (a lazy list pointer) in the variable start, then captures it again at EOF, and uses the ancient Lisp function ldiff to calculate the output:

$ txr -c '@(maybe) @(skip) @/pattern/ @(end) @(data start) @(skip) @(eof) @(data end) @(do (tprint (ldiff start end)))' - 

The start is captured after optionally matching some lines followed by the pattern. If the pattern doesn't occur, it's as if this @(maybe)...@(end) block isn't there, and the start of the data is captured.

In short, "maybe skip some lines ending in pattern; in either case, note the position as start; then skip to EOF and note the position as the end; print all between start and end".

TXR solution, on the command line:

 $ txr -c '@(maybe) @(skip) @(trailer) @/pattern/ @(end) @(repeat) @line @(do (put-line line)) @(end)' - 

Example: lines in which pattern doesn't occur. Code abbreviated:

 $ txr -c '@(maybe) [...]' - a b c d Ctrl-DEnter a b c d 

When pattern occurs:

$ txr -c '@(maybe) [...] @(end)' - a b c pattern pattern x x y y z z Ctrl-DEnter 

As you can see, once pattern occurs, the lines start being echoed from then on.

The logic is very simple: material enclosed in @(maybe)...@(end) is optionally matched. There we have a @(skip) which skips any number of lines, followed by a @(trailer) which means "match the following as a trailing context (do not consume it)". (This feature and its name is inspired by the slash trailing contexts in Lex.) If we take out @(trailer) then the line which matches the pattern is excluded from the output.

Of course @/pattern/ is a regex. It is implicitly anchored: it must match the whole line. So to match a line which contains abc we would use @/.*abc.*/ or @(skip)abc@(skip).

In the case when the pattern doesn't occur, the skip inside maybe scans the entire input, and eventually fails. maybe catches this failure and sweeps it under the rug, producing a success. The material which follows the maybe is then matched, against the original input on which the interior of maybe failed (i.e. start of the stream).

At the end we we have an repetitive matching structure, @(repeat), which contains an output side effect.

TXR solution, on the command line:

 $ txr -c '@(maybe) @(skip) @(trailer) @/pattern/ @(end) @(repeat) @line @(do (put-line line)) @(end)' - 

Example: lines in which pattern doesn't occur. Code abbreviated:

 $ txr -c '@(maybe) [...]' - a b c d Ctrl-DEnter a b c d 

When pattern occurs:

$ txr -c '@(maybe) [...] @(end)' - a b c pattern pattern x x y y z z Ctrl-DEnter 

As you can see, once pattern occurs, the lines start being echoed from then on.

The logic is very simple: material enclosed in @(maybe)...@(end) is optionally matched. There we have a @(skip) which skips any number of lines, followed by a @(trailer) which means "match the following as a trailing context (do not consume it)". (This feature and its name is inspired by the slash trailing contexts in Lex.) If we take out @(trailer) then the line which matches the pattern is excluded from the output.

Of course @/pattern/ is a regex. It is implicitly anchored: it must match the whole line. So to match a line which contains abc we would use @/.*abc.*/ or @(skip)abc@(skip).

In the case when the pattern doesn't occur, the skip inside maybe scans the entire input, and eventually fails. maybe catches this failure and sweeps it under the rug, producing a success. The material which follows the maybe is then matched, against the original input on which the interior of maybe failed (i.e. start of the stream).

At the end we we have an repetitive matching structure, @(repeat), which contains an output side effect.

A different TXR solution which uses the @(data ...) directive to capture the current data cursor (a lazy list pointer) in the variable start, then captures it again at EOF, and uses the ancient Lisp function ldiff to calculate the output:

$ txr -c '@(maybe) @(skip) @/pattern/ @(end) @(data start) @(skip) @(eof) @(data end) @(do (tprint (ldiff start end)))' - 

The start is captured after optionally matching some lines followed by the pattern. If the pattern doesn't occur, it's as if this @(maybe)...@(end) block isn't there, and the start of the data is captured.

In short, "maybe skip some lines ending in pattern; in either case, note the position as start; then skip to EOF and note the position as the end; print all between start and end".

Source Link
Kaz
  • 8.9k
  • 2
  • 31
  • 52

TXR solution, on the command line:

 $ txr -c '@(maybe) @(skip) @(trailer) @/pattern/ @(end) @(repeat) @line @(do (put-line line)) @(end)' - 

Example: lines in which pattern doesn't occur. Code abbreviated:

 $ txr -c '@(maybe) [...]' - a b c d Ctrl-DEnter a b c d 

When pattern occurs:

$ txr -c '@(maybe) [...] @(end)' - a b c pattern pattern x x y y z z Ctrl-DEnter 

As you can see, once pattern occurs, the lines start being echoed from then on.

The logic is very simple: material enclosed in @(maybe)...@(end) is optionally matched. There we have a @(skip) which skips any number of lines, followed by a @(trailer) which means "match the following as a trailing context (do not consume it)". (This feature and its name is inspired by the slash trailing contexts in Lex.) If we take out @(trailer) then the line which matches the pattern is excluded from the output.

Of course @/pattern/ is a regex. It is implicitly anchored: it must match the whole line. So to match a line which contains abc we would use @/.*abc.*/ or @(skip)abc@(skip).

In the case when the pattern doesn't occur, the skip inside maybe scans the entire input, and eventually fails. maybe catches this failure and sweeps it under the rug, producing a success. The material which follows the maybe is then matched, against the original input on which the interior of maybe failed (i.e. start of the stream).

At the end we we have an repetitive matching structure, @(repeat), which contains an output side effect.