-1

How to force m4 to continue processing line if value has hash?

$ echo a a a | m4 -D a=B+
B+ B+ B+
$ echo a a a | m4 -D a=B#
B# a a

I want identical behavior for second case - is it possible? (all three occurrences to be replaced).

In my understanding observed behavior is inconsistent and I couldn't find explanation in user manual.

melpomene
  • 84,125
  • 8
  • 85
  • 148
noonex
  • 1,975
  • 1
  • 16
  • 18

1 Answers1

4

The # character is the first character of a comment and a newline is the last character. The m4 parses the first a and replace it to B#. It doesn't scan more because it runs into a comment.

The solution is to change the comment characters with changecom:

$ echo "changecom(BC,EC)a a a" | m4 -D a=B#
B# B# B#

Of course you can choose better comment begin- and end-sequences.

Ps. you can turn off the comment with simple changecom without arguments: echo changecom a a a. You can read it from manual :)

uzsolt
  • 5,832
  • 2
  • 20
  • 32
  • Thank you a lot. I worked around the problem for now, but it still looks inconsistent behavior. What if value (which I take from third party), will contain another changecom() ? So far I am getting 'stack overflow' with: echo "changecom(BC,EC)a a a" | m4 -D 'a=B#changecom(a)' . I will accept the answer though, but I really still don't understand current approach conceptually and how to deal with it. – noonex Jan 06 '17 at 20:45
  • I think conceptually comments must be stripped out before processing, but anyway it looks edge case problem and the tool may be useful with workarounds – noonex Jan 06 '17 at 20:48
  • It isn't inconsistent behavior, it's well documented. `m4` parses its input and search for known keywords (and macros) and "replace" it to their definition. If you want include a file and don't want to parse, you can use `paste`. Or if it helps, you can use `-P` option to `m4`. Or... If you want to use a tool you should know it :) – uzsolt Jan 07 '17 at 13:14
  • Obviously it does more - it searches not only in input, but recursively in output as well. If I need to replace parameter with path to a file, (which theoretically may contain any character and any keyword) - there is no flag, which will protect my script. I can live with it - but in my understanding m4 should have a flag to disable comment detection in own output. E.g. with cpp preprocessor you just cannot insert new comment into generated output, which I consider more consistent behavior. – noonex Jan 08 '17 at 22:33
  • I don't understand you exactly but maybe you want to use the ` and ' characters: in this case `m4` will work with it as a string: include(\`include/foo.bar') will include the file `include/foo.bar`. If you don't want allow to `m4` to processing the included file, use the `paste` macro :) – uzsolt Jan 11 '17 at 16:18