Regexp Search and Replace for Words with Dash (Hyphen)

Your code dynamically constructs a string representing a filter expression. Great. You now need to evaluate it as a filter expression.

The first filter evaluation constructs your filter expression, the second evaluates it.

Try this:

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
>

<$text text={{{
      [<in>search-replace:gm:regexp<pat>,<rep>] :map[subfilter<currentTiddler>]
}}}/>

</$let>
1 Like

BTW, there is no need at all for the ::: stuff in there. That just makes it way easier to debug things, because they stand out more than &nbsp;

For those who don’t care about easy visual things for debugging, the following should work (but I have not tried):

<in>search-replace:g[ ],[&nbsp;]search-replace:gm:regexp<pat>,<rep>] ] }}}

1 Like

But that still strips out spaces. Obviously I can use Charlie’s technique, but I really want something simpler to work. I may simply have to get used to disappointment.

Know TiddlyWiki and think as TiddlyWiki is, and there is no struggle and have no disappointment.

Do not know TiddlyWiki and think as not TiddlyWiki is, and you will struggle and have disappointment.

I am happy as a clam, because I think as TiddlyWiki is, and it works as I think.

You are getting in your own way. Empty your cup.

Yes, I’ve watched Kung Fu Panda a few too many times …

It may not be relevant but when splitting titles or strings to perform operations on them you can use +[join[ ]] containing a space to rejoin them restoring the spaces.

Thank you all, I am really enjoying reading all these wonderful discussions. Actually, this question raised to improve the APA titlecase in Refnotes plugin and I am solving parts of a bigger puzzle where all APA titlecase rules apply one by one.

I also realized the below code works fine:

<$let in="simple-words, some text, to-do">

<$text text={{{
  [<in>split[ ]]
  :map[regexp[-]split[-]titlecase[]join[-]else<currentTiddler>]
  :and[join[ ]]
  }}}
/>

</$let>

This is another version.

  • It makes all words titlecase
  • It only makes the second part titlecase, if it is a major word (has four characters in length)
  • It handles em-dash and where extra dashes are existed
  • It handles multipart hyphenated words like multi-part-word or multi-part--words
\define punc() . , ? ! ; :
\define pat() \w+[-]+\w+(-\w*)?
\define hyphenated-major()  [split[-]last[]split[]]:except[enlist<punc>]:and[join[]length[]compare:number:gt[3]]

\define hyphen() [regexp<pat>filter<hyphenated-major>split[-]titlecase[]join[-]else{!!title}]

<$let in="simple-words, some text, to--do and three---doit">

<$text text={{{
[<in>split[ ]titlecase[]]
:map:flat[subfilter<hyphen>]
:and[join[ ]]

  }}}
/>

</$let>

produces

Simple-Words, Some Text, To--do And Three---Doit

Thanks to the :map filter run prefix where it allows to build pipeline (@saqimtiaz)

A post was merged into an existing topic: Dynamic Filters in One Go

But these also fail me, using the replacement as a literal instead of filling it in:

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
>

<$text text={{{
      [<in>search-replace:gm:regexp<pat>,<rep>]
}}}/>

</$let>

and

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
  out={{{ [<in>search-replace:gm:regexp<pat>,<rep>] }}}
>

<<out>>

</$let>

There’s always so much to learn. Every time I think I’ve made progress, I seem to take a step backward!

But these also fail me, using the replacement as a literal instead of filling it in:

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
>

<$text text={{{
      [<in>search-replace:gm:regexp<pat>,<rep>]
}}}/>

</$let>

and

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
  out={{{ [<in>search-replace:gm:regexp<pat>,<rep>] }}}
>

<<out>>

</$let>

There’s always so much to learn. Every time I think I’ve made progress, I seem to take a step backward!

A post was merged into an existing topic: Dynamic Filters in One Go

But these also fail me, using the replacement as a literal instead of filling it in:

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
>

<$text text={{{
      [<in>search-replace:gm:regexp<pat>,<rep>]
}}}/>

</$let>

and

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
  out={{{ [<in>search-replace:gm:regexp<pat>,<rep>] }}}
>

<<out>>

</$let>

There’s always so much to learn. Every time I think I’ve made progress, I seem to take a step backward!

etc… is not valid in Tiddlywiki ?

This is part of the syntax for search-replace::regex. It refers back to a group captured in the regular expression parsing.

From https://tiddlywiki.com/#search-replace%20Operator%20(Examples):

You can also use regular expression capture groups in the replacement string: \define names() (\w+)\s(\w+)

[[John Smith]search-replace::regexp<names>,[$2,$1]]

This yields:

The JavaScript regex reference page has more information; the bits on capturing groups is relevant to TW/

$1 is syntax for regexp in search and replace.

https://tiddlywiki.com/#search-replace%20Operator%20(Examples)

(Oops, just noticed that @Scott_Sauyet already pointed that out. Apologies for yammering the same info!)

But these also fail me, using the replacement as a literal instead of filling it in:

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
>

<$text text={{{
      [<in>search-replace:gm:regexp<pat>,<rep>]
}}}/>

</$let>

and

<$let 
  in="simple-words, some text, to-do"
  pat=(\w)(\w*)(-+)(\w)(\w*)
  rep="[[$1]uppercase[]addsuffix[$2]addsuffix[$3]] [[$4]uppercase[]addsuffix[$5]] +[join[]]"
  out={{{ [<in>search-replace:gm:regexp<pat>,<rep>] }}}
>

<<out>>

</$let>

There’s always so much to learn. Every time I think I’ve made progress, I seem to take a step backward!

I often say “it’s gonna get a little ugly before it gets better.”

That step back kind of compresses a spring that’s going to give you that forward bounce. Maybe a few bumps and bruises as the direction is slightly askew, but every step back gets you projected closer to target.

Now I’ve got Super Dave Osborne in my thoughts for some reason…

Oh I see, outside of the search and replace they are just strings, use to gnerate a search and replace “query”.