[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Multiple successive "patsubst"s…
From: |
Grant Taylor |
Subject: |
Re: Multiple successive "patsubst"s… |
Date: |
Wed, 19 Sep 2018 09:54:41 -0600 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 |
Thank you for your help Eric. That's what I needed.
On 09/19/2018 08:22 AM, Eric Blake wrote:
What changequote() settings are you using?
I changed quotes (my first time ever in m4) while working on this. I
now have:
changequote(`[', `]')
The patsubst now looks like this:
patsubst([$1], [ ], [\\ ])
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.
ACK
I changed quotes at the start of my file and updated all subsequent
lines accordingly.
Here's an example, without the problematic ' and with the default `'
quoting characters:
patsubst(``Grant Taylors Blog (:test:)'', `\([ :()]\)', `\\\1')
Grant\ Taylors\ Blog\ \(\:test\:\)
How did I miss both the range […] and back references \(…\). I guess I
thought patsubst(…) was simple replacement, particularly considering
that regexp(…) is a separate macro.
That is definitely an improvement. (I just commented out the copy using
changed quotes, uncommented and adjusted original version.)
Wrapping that in a macro:
define(`escape', `patsubst(``$1'', `\([ :()]\)', `\\\1')')dnl
escape(`Grant Taylors Blog (:test:)')
Grant\ Taylors\ Blog\ \(\:test\:\)
ACK
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 just tried the following, based on your recommendation, and seems to
do what I want. Or at least I need to do more analysis and see if it
does or does not correctly modify the data the way that I want.
changequote(`{', `}')
patsubst({$1}, {\([' :()]\)}, {\\\1})
Actually, in sed, it would be:
s/\([ :()']\)/\\\1/g
O.o? I'd swear that I tested (command line didn't work (b/c of
quoting), but sed file did). But it's somewhat moot as it got the point
across and you were able to provide the help with patsubst that I needed.
It may also be easier to help debug if you paste what you've tried.
Fair.
Note that one-character quotes that might occur imbalanced in your
text are inherently difficult to manage correctly through pattern
substitutions;
Fortunately (for me) this particular project doesn't care about
imbalanced quotes in the input text. In fact, there will purposefully
be imbalanced quotes in the incoming text. Most frequently the
apostrophe used to mark possession, "Grant's Blog", type thing.
Nor do I expect to have anything unbalanced in my m4 code.
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 ]]).
Fair enough. I had used "[" and "]" for a while yesterday afternoon.
This morning I've switched to "{" and "}" and things seem to be working
as I want them to.
Here's a (sanitized) copy of the core of the code that I'm working on.
changequote(`{', `}')
define({rss}, {# $1
:0 E
* for <ifelse(index({$2}, address@hidden), {-1}, {translit({patsubst({$1}, { },
{})}, {A-Z}, {a-z})@r{}ss.example.com}, {$2})>;
.maildir/.RSS.patsubst({$1}, {\([' :()]\)}, {\\\1})/
})
The purpose of the code is to be able to successively call the rss macro
to build Procmail recipes. — Ultimately I'll redefine the macros to
output Maildrop rules. That way I can use the same input data to
generate different output.
Input:
rss(one)
rss(two three)
rss(four's five)
rss({six :: seven (eight)})
Output:
# one
:0 E
* for <address@hidden>;
.maildir/.RSS.one/
# two three
:0 E
* for <address@hidden>;
.maildir/.RSS.two\ three/
# four's five
:0 E
* for <four'address@hidden>;
.maildir/.RSS.four\'s\ five/
# six :: seven (eight)
:0 E
* for <six::seven(eight)@rss.example.com>;
.maildir/.RSS.six\ \:\:\ seven\ \(eight\)/
The input listed above is MUCH easier to maintain and can be worked with
programmatically, including sorting the lines in the input file.
Thank you again for your help Eric. That's what I needed. :-)
--
Grant. . . .
unix || die
smime.p7s
Description: S/MIME Cryptographic Signature