Skip to main content
added 2347 characters in body
Source Link
Kaz
  • 8.9k
  • 2
  • 31
  • 52
$ txr -e '(awk (:let tmp)  (:begin (set ofs "\t"))  (f (set tmp (pop f)) (ff (keep-if #/cow|dog/)) (push tmp f) (prn)))' data A dog999 dog284 cow284 cow432 B cow394 cow432 cow345 dog983 C dog847 cow395 dog496 D dog392 cow237 cow749 

Sundeep's Perl solution roughly translates to the awk macro like this:

$ txr -e '(awk (t (prn `@[f 0]\t@{(keep-if #/cow|dog/ [f 1..:]) "\t"}`)))' data 
$ txr -e '(awk (:let tmp) (f (set tmp (pop f)) (ff (keep-if #/cow|dog/)) (push tmp f) (prn)))' data A dog999 dog284 cow284 cow432 B cow394 cow432 cow345 dog983 C dog847 cow395 dog496 D dog392 cow237 cow749 
$ txr -e '(awk (:let tmp)  (:begin (set ofs "\t"))  (f (set tmp (pop f)) (ff (keep-if #/cow|dog/)) (push tmp f) (prn)))' data A dog999 dog284 cow284 cow432 B cow394 cow432 cow345 dog983 C dog847 cow395 dog496 D dog392 cow237 cow749 

Sundeep's Perl solution roughly translates to the awk macro like this:

$ txr -e '(awk (t (prn `@[f 0]\t@{(keep-if #/cow|dog/ [f 1..:]) "\t"}`)))' data 
added 2347 characters in body
Source Link
Kaz
  • 8.9k
  • 2
  • 31
  • 52

TXR awk macro:

$ txr -e '(awk (:beginlet (settmp) fs "\t" ofs fs))  (tf (set [f 1..:]tmp (keep-ifpop f))  (opff search(keep-regex @1if #/cow|dog/))   [f 1..:]))    (push tmp f) (prn)))' data A dog999 dog284 cow284 cow432 B cow394 cow432 cow345 dog983 C dog847 cow395 dog496 D dog392 cow237 cow749 

Breakdown:

  1. The :let clause in the macro specifies local variables. This macro implements the "Awk Paradigm" but in a type-safe language, in which variables have to be defined before use. So in addition to clauses like :begin and :end (analogous to BEGIN and END in POSIX Awk), this Awk provides :let for defining variables that are lexically scoped to the macro.

  2. (f (set tmp (pop f)) ...) is a condition-action clause, where the condition is f. If is the list of delimited fields from the record; if it is not empty (not equal to nil) then it behaves like Boolean true. So the action forms execute if there is anything in f.

  3. (set tmp (pop f)) pops the first field from the list and saves it in the temporary variable tmp. The second field becomes first, the third second and so on. When we operate on f, the record rec is also reconstituted automatically using ofs, just like in POSIX Awk, the $0 record is reconstituted using OFS between the fields.

  4. (ff ...) filters the fields through an operation, in this case (keep-if #/regex/). Basically we remove from f all the fields that don't match the regex. ff is an operator visible inside the awk macro. keep-if is a regular function; here it is implicitly curried, so the list argument doesn't appear. It expects a predicate function, but a regex is function-callable, so suitable as a predicate.

  5. Then we push back the previously saved first field onto the field list f with (push tmp f).

  6. (prn) is the equivalent of print. With no arguments, it prints the record, followed by the output record separator (ors) which is initialized to newline. Since rec has been reconstituted after all the manipulations of f, we get the filtered output.

As can be seen, the Awk paradigm is basically intact, just in the context of a different language in which different kinds of things are possible. The convenience of just being able to do $2 > $1 without checking that these fields actually exists is not there; but on the other hand, we don't have to write loops to process the fields as a data structure. Fields can be mapped through functions or treated as a stack.

$ txr -e '(awk (:begin (set fs "\t" ofs fs)) (t (set [f 1..:] (keep-if (op search-regex @1 #/cow|dog/) [f 1..:]))    (prn)))' data A dog999 dog284 cow284 cow432 B cow394 cow432 cow345 dog983 C dog847 cow395 dog496 D dog392 cow237 cow749 

TXR awk macro:

$ txr -e '(awk (:let tmp)   (f (set tmp (pop f))  (ff (keep-if #/cow|dog/))   (push tmp f) (prn)))' data A dog999 dog284 cow284 cow432 B cow394 cow432 cow345 dog983 C dog847 cow395 dog496 D dog392 cow237 cow749 

Breakdown:

  1. The :let clause in the macro specifies local variables. This macro implements the "Awk Paradigm" but in a type-safe language, in which variables have to be defined before use. So in addition to clauses like :begin and :end (analogous to BEGIN and END in POSIX Awk), this Awk provides :let for defining variables that are lexically scoped to the macro.

  2. (f (set tmp (pop f)) ...) is a condition-action clause, where the condition is f. If is the list of delimited fields from the record; if it is not empty (not equal to nil) then it behaves like Boolean true. So the action forms execute if there is anything in f.

  3. (set tmp (pop f)) pops the first field from the list and saves it in the temporary variable tmp. The second field becomes first, the third second and so on. When we operate on f, the record rec is also reconstituted automatically using ofs, just like in POSIX Awk, the $0 record is reconstituted using OFS between the fields.

  4. (ff ...) filters the fields through an operation, in this case (keep-if #/regex/). Basically we remove from f all the fields that don't match the regex. ff is an operator visible inside the awk macro. keep-if is a regular function; here it is implicitly curried, so the list argument doesn't appear. It expects a predicate function, but a regex is function-callable, so suitable as a predicate.

  5. Then we push back the previously saved first field onto the field list f with (push tmp f).

  6. (prn) is the equivalent of print. With no arguments, it prints the record, followed by the output record separator (ors) which is initialized to newline. Since rec has been reconstituted after all the manipulations of f, we get the filtered output.

As can be seen, the Awk paradigm is basically intact, just in the context of a different language in which different kinds of things are possible. The convenience of just being able to do $2 > $1 without checking that these fields actually exists is not there; but on the other hand, we don't have to write loops to process the fields as a data structure. Fields can be mapped through functions or treated as a stack.

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

$ txr -e '(awk (:begin (set fs "\t" ofs fs)) (t (set [f 1..:] (keep-if (op search-regex @1 #/cow|dog/) [f 1..:])) (prn)))' data A dog999 dog284 cow284 cow432 B cow394 cow432 cow345 dog983 C dog847 cow395 dog496 D dog392 cow237 cow749