Return substring from string expression

Hi folks,

I’m searching for a way to return the first [n] characters from a string. In the first step I also need to filter out non-alphanumeric characters, so I decided to use a RegEx for this task.
While the RegEx works in the way I want I couldn’t find a solution to return only the first 20 characters of the output.

\define regexalphanum() [^A-z0-9\-_]

<$text text={{{[[{{TiddlerTitle!!Field1))//AndOther--Chars?!.}}]search-replace:g:regexp<regexnonalphanum>,[]]}}} />

Output:

TiddlerTitleField1AndOther–Chars

My guess is that there is a quantifier operator needed, but I didn’t figure it out how to use it right. It works with a string (tested at regex101.com), but unfortunately not in TW.

\define regexnonalphanum() [^A-z0-9\-_]
\define regexlimit20() [^.{20}]

<$let var1={{{ [[{{TiddlerTitle!!Field1))//AndOther--Chars?!.}}]search-replace:g:regexp<regexnonalphanum>,[]] }}} >
<<var1>><br>
<$let var2={{{ [<var1>regexp<regexlimit20>] }}} >
<<var2>><br><br>

Output:

TiddlerTitleField1AndOther–Chars
TiddlerTitleField1AndOther–Chars

Thank you in advance for your suggestions.

Not a full answer but if you use a regular split, with no value it splits on every character; You can then ask for the first N, and then re"join" them.

{{{ [[This is my string]split[]first[3]join[]] }}}
1 Like

Tones beat me to it, but taking your string as a starting point, this works for the first 6 characters:

<$text text={{{ [[{{TiddlerTitle!!Field1))//AndOther--Chars?!.}}]search-replace:g:regexp<regexnonalphanum>,[]split[]first[6]join[]] }}} />
1 Like

Thank you, @TW_Tones and @Springer - both suggestions work as expected!

What I’m still curious about is, if TW-Filter-Operations are capable of returning true substrings, too -
like substring[start,end] of a string. With first- and last-operators it is possible to get “left-side-string” or “right-side-string”, but how can a “mid-string” being returned?

Or do I have to rely on RegEx-operations for this case?
I have no real clue how such RegEx-constructions should look like.

There could be a more elegant solution, but split[]first[10]last[8]join[] gets you from character 3 through character 10.

Slightly more semantic: split[]first[10]butfirst[2]join[]

1 Like

Look through the filter operators and see first last nth zth butfirst etc… There are plenty of choices including regular expressions.

2 Likes

If you want a function version of this, something like this should do:

\function sub.string(start, end) 
  [split[]first<end>join[]addprefix[ ]split[]butfirst<start>join[]]
\end

It behaves like this:

[[abcdefghijklmnopqrstuvwxyz]sub.string[3],[7]]: “cdefg
(inclusive on both ends)

[[abcdefghijklmnopqrstuvwxyz]sub.string[24],[30]]: “xyz
(ignores extra characters at end)

[[abdedfgh]] [[ijklmnopq]] [[rstuvwxyz]] :map[sub.string[2],[6]] +[join[ - ]]: “bdedf - jklmn - stuvw

It doesn’t properly ignore an additional character at the beginning (sub.string[0],[10]) so it probably needs a little work. Also, a more common substring operator, such as the one in JS is inclusive at the start, exclusive at the end. I’m not sure which I prefer for TW.

4 Likes

good approach, i like it because i can understand it.
There are certainly other solutions that use RegEx, for example.
But it’s of little use to me if I don’t know the required syntax - it’s better if I can use TiddlyWIki on-board tools for this.

2 Likes

I bookmarked the page with an overview of the Filter Operators!
Very useful and I don’t know why I didn’t saw this earlier.
Thank you :slight_smile:

Excellent solution, this will come in handy for future versions of my personal wiki.
I can understand why it isn’t perfect but at the moment this is even more than I needed (look at the first posts from TW_Tones and Springer) - very good idea, thank you!