1

Background

Looking to replace periods with dollar signs only within text that is delimited by dollar signs (never spanning lines). For example:

Names: $annie.bettie.cindy.dannie.ellie$. Only $a$ names. $a.b.c.d.e.f$.

Problem

The following regex almost works, but is too simple:

/([[:alnum:]])\.([[:alnum:]])/g

If a match exists outside of the delimiters ($), then too much will be replaced.

The following regex:

/\$.*?\$/g

Matches and groups the delimited strings:

Names: $annie.bettie.cindy.dannie.ellie$. Only $a$ names. $a.b.c.d.e.f$.

Question

How do I combine the two regular expressions so that the periods can be replaced with another string? For example:

Names: $annie.bettie.cindy.dannie.ellie$. Only $a$ names. $a.b.c.d.e.f$.

Ultimately will become:

Names: `r v$annie$bettie$cindy$dannie$ellie`. Only `r v$a` names. `r v$a$b$c$d$e$f`.

The trouble I'm having is matching the delimited dots.

The regular expression will be piped into sed from a terminal running bash.

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
  • 2
    Maybe [this SO thread](http://stackoverflow.com/questions/25241413/pass-the-matched-value-to-a-function-and-replace-with-the-return-value) can throw some light. – Wiktor Stribiżew Sep 28 '16 at 06:58
  • 1
    can you explain your expected output? problem statement said you need to replace `.` with `$` within `$sometext$` pattern.. particularly I don't get the ```r v``` part as well as the missing `$` at end of pattern – Sundeep Sep 28 '16 at 07:08
  • @Sundeep: The goal is to create a regex that converts simple [Pandoc](http://pandoc.org/) YAML variable references to the more powerful inline [knitr](http://yihui.name/knitr/) expressions. – Dave Jarvis Sep 28 '16 at 15:51

2 Answers2

1

This might work for you (GNU sed):

sed -r ':a;s/^(([^$]*\$[^$.]*\$)*[^$]*\$[^$.]*)\./\1\n/;ta;s/(\$[^$]*)\$/`r v\1`/g;y/\n/$/' file

Replace all periods within the groups by a newlines. Insert groups prefix and suffix literals and then translate the newlines to dollars.

potong
  • 55,640
  • 6
  • 51
  • 83
1
$ cat ip.txt 
Names: $annie.bettie.cindy.dannie.ellie$. Only $a$ names. $a.b.c.d.e.f$.

$ perl -pe '
BEGIN
{
    sub f
    {
        $a = $_[0] =~ tr/./$/r;
        $a =~ s/^/`r v/;
        $a =~ s/.$/`/;
        return $a;
    }
}
s/\$.*?\$/f($&)/ge
' ip.txt
Names: `r v$annie$bettie$cindy$dannie$ellie`. Only `r v$a` names. `r v$a$b$c$d$e$f`.
  • The subroutine f performs the necessary transformation for $sometext$ strings - first transliterate . to $, then add some string to beginning and finally remove last character to replace with required format
    • The subroutine is put in a BEGIN block, which is executed before processing the input file line by line
  • s/\$.*?\$/f($&)/ge will extract the $sometext$ pattern and pass on to f subroutine. Perl knows to call it courtesy the e flag
  • -p switch means input line gets printed after all commands
Sundeep
  • 23,246
  • 2
  • 28
  • 103