[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Multiple successive "patsubst"s…
From: |
Eric Blake |
Subject: |
Re: Multiple successive "patsubst"s… |
Date: |
Wed, 19 Sep 2018 09:22:09 -0500 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 |
On 9/18/18 6:26 PM, Grant Taylor wrote:
I need some help with multiple successive "patsubst" statements.
I have a string of text like "Grant Taylor's Blog (:test:)" (accessible
to a macro as $2) that I need to escape spaces, apostrophes, colons, and
parenthesis. I need the output of the above string to be "Grant\
Taylor\'s\ Blog\ \(\:test\:\)".
What changequote() settings are you using? That particular string is
awkward with the default `' quoting (since it contains ' itself, and
since you want to modify ' into \'). Note that your choice of
changequote needs to be made early, before defining other macros, as the
operation of user-defined macros depends heavily on the quoting in effect.
I can get patsubst to replace one or more occurrences of any single
character. But I can't seem to get things correct to replace (escape)
multiple different characters.
I have looked at the documentation of translit and think that it would
handle multiple characters, but I don't see how to add the leading
forward slash to escape said characters.
Here's an example, without the problematic ' and with the default `'
quoting characters:
patsubst(``Grant Taylors Blog (:test:)'', `\([ :()]\)', `\\\1')
Grant\ Taylors\ Blog\ \(\:test\:\)
Wrapping that in a macro:
define(`escape', `patsubst(``$1'', `\([ :()]\)', `\\\1')')dnl
escape(`Grant Taylors Blog (:test:)')
Grant\ Taylors\ Blog\ \(\:test\:\)
Now with altered changequotes, so that you can also handle and escape an
embedded ':
changequote([[,]])
define([[escape]],[[patsubst([[[[$1]]]], [[\([ :()']\)]], [[\\\1]])]])
escape([[Grant Taylor's Blog (:test:)]])
Grant\ Taylor\'s\ Blog\ \(\:test\:\)
I think I could do what I want to do with the following regular
expression in sed. But I want to do this in m4, for various reasons.
s/\([ :()]\)/\1/g
Actually, in sed, it would be:
s/\([ :()']\)/\\\1/g
It may also be easier to help debug if you paste what you've tried.
Note that one-character quotes that might occur imbalanced in your text
are inherently difficult to manage correctly through pattern
substitutions; using a two-character quote delimiter that is unlikely to
appear in any of the text you are processing can make life much easier
(I chose [[ and ]]).
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org