How to repeat the nonblank string?

In place modification of a list works well here:

fc[list_] := Module[{out=list},
    With[{empty = Pick[Range[2,Length@list], Rest@list,""]},
        out[[empty]]=out[[empty-1]]
    ];
    out
]

A comparison with Mr Wizard's fn:

data = RandomChoice[{"","","","a","b"}, 10^5];
r1 = fn[data]; //AbsoluteTiming
r2 = fc[data]; //AbsoluteTiming
r1 === r2

{0.049858,Null}

{0.01092,Null}

True


As I presently interpret the question

(Now with refinements after considering Chris Degnen's simultaneous answer)

fn[list_] :=
  Partition[list, 2, 1, -1, ""] // Cases[{p_, ""} | {_, p_} :> p]

Test:

 {"", "x", "y", "", "z", ""} // fn
{"", "x", "y", "y", "z", "z"}

Patterns

Since you seem only to be interested in a pattern-matching solution here is my proposal to avoid the extremely slow use of ReplaceRepeated while still using pattern-matching as the core of the operation.

fn2[list_] :=
  list // ReplacePart @ 
   ReplaceList[list, {a___, p_, "", ___} :> (2 + Length@{a} -> p)]

Recursive replacement

I just realized that this is a perfect time to use a self-referential replacement:

fn3[list_] :=
  list /. {a___, p_, "", b___} :> {a, p, p, ##& @@ fn3@{b}}

Benchmark

All three methods are much faster than kglr's foo (note the log-log scale).

Now with Carl Woll's fc, the fastest method yet. ( but no patterns ;-) )

Needs["GeneralUtilities`"]

$RecursionLimit = 1*^5;

BenchmarkPlot[{foo, fn, fn2, fn3, fc},
  RandomChoice[{"", "", "", "a", "b"}, #] &
]

enter image description here


Update:

foo = # //. {a___, p : Except["", _String], Longest[b : "" ..],   c___} :>
   {a, p, p, ## & @@ ConstantArray["☺", Length[{b}] - 1], c} /. "☺" -> "" &;

{"", "", "", "3$71", "", "", "2$72", "", "", "", ""} // foo

{"", "", "", "3$71", "3$71", "", "2$72", "2$72", "", "", ""}

Previous post:

rule = {a___, p : Except["", _String], Longest["" ..],  b___} :> {a, p, p, b};

{"", "", "", "3$71", "", "", "2$72", "", "", "", ""} //. rule

{"", "", "", "3$71", "3$71", "2$72", "2$72"}