Regex find and replace only between two strings

I’m looking for a way to find and replace text only within the YAML front matter in Obsidian markdown files.

The YAML front matter begins and ends with —, like this:


tags: activities, mac
date:

I’m thinking this is beyond the power of regex. You need to select the text between the two “—” and then do a find/replace within that selection. It seems like some app would have to drive this–and be able to do it for all files in a folder.

I’ve written BBEdit tech support, and will post here if I learn anything from them.

Thanks,
Russell

You should be able to do that using a multiple line matching statement.
Like this (click the link below to go to regex101.com where you can see it explained):

/—[\S\s]+tags:\s*(.+).+[\S\s]±–/gm

That captures everything after tags: and an optional space, until the end of the line.

An app like TextSoap should be able to do that without the overhead of BBEdit.

I find it useful to have something like Patterns or Expressions around to help work out patterns that you need to execute. There is also an Obsidian plugin (Regex Find and Replace) that might be useful.

Can you talk more about why you need to limit the find and replace to the YAML header? My approach when doing this on my files is to regex for each key one at a time: ^tags:(.*) and do replacements that way.

I only have those key words with a colon after them in my YAML front matter, so there isn’t a concern with replacing “tags” elsewhere in the file.

1 Like

What tool(s) are you using or willing to use?

If you’re using javascript, Python or really any programming language, there are libraries for managing YAML – I would use those.

Curious if there are any features in Patterns or TextSoap that are not in https://regexr.com/ ?

I’m sure there are numerous regex tut sources – I just pointed out the ones I use.

BTW – TextSoap is not a regex tut app. It is an app used to modify text according to user-defined rules, among which can be regular expressions.

1 Like

I was thinking that this YAML question was just one (real) example of the larger question: Is there a way to do a search/replace between ANY two strings, anywhere in a file?

In this YAML case, you’ve shown me that it is simpler, since anything in the header will begin the line with a word followed by a colon. In your example: ^tags:(.*), where do I put the string I want to replace on the Tags: line?

Specifically, I mistakenly put # before each tag, then later learned you don’t use the hash for tags in YAML, so I want to delete hashes in the header, but not elsewhere in the file, which would of course trash all the headings.

Thanks. A little basic regex is as close to programming as I can go, though I wouldn’t mind applying “rote” techniques to solve specific situations. It’s just a “rabbit hole” I can’t afford to enter.

2 Likes

So if I wanted to find hashes (#) between — and — (YAML header boundaries), where would I put the hash in your multiple line matching statement?

And if that could find the hash, what would go in the “replace with” box in something like BBEdit? Probably referencing sub patterns?

Thanks,
Russell

I hope you are working only with a copy of the file you want to change, although it doesn’t sound like it. :upside_down_face: (I’d love to be wrong…)

@rbanks88 If you want to use BBEdit to selectively remove all hashtags from a tags: line in a YAML header without removing any hashtags from any other YAML line or the note body, enter the following in the BBEdit search dialog:

Find:

(---.*?\r(?:(?!---).*\r)*?tags: .*?)#(\w+.*?\r(?:(?!---).*\r)*?---)

Replace:

\01\02

Important notes:

  1. Make sure you backup your notes before running any search/replace actions.
  2. You need to run the above search/replace action multiple times – as many times as you have tags in a single tags: line.

Example:

As an example, run the above search/replace action twice to clean this sample note:

--- # YAML comment
foo: bar, baz # another YAML comment
authors:
  - Russell Banks
  - Matthias Steffens
tags: #tag1, #tag2
date: 20220315
---


# heading 1

Some text and an inline tag: #tag3

## heading 2

Some more text containing a MultiMarkdown citekey ([#Banks2022]).

This would convert the line tags: #tag1, #tag2 in the above sample note to tags: tag1, tag2 with any other content being left untouched.

The above search/replace pattern would also work with multiple YAML blocks in the same note, and also with a multi-file search in BBEdit.

If you use vi, you can specify the lines the regex applies to 1,10 for example.

Thanks for taking the time to give the deails, Matthias.

1 Like

Of course everything’s backed up (twice) , and I test before running batch replaces in BBEdit. :slight_smile:

1 Like