What is the formal syntax surrounding tags?

In case it helps others, I had to answer this one myself. If looks like the following regular expression will work:

(^|[[:blank:]])(#[a-zA-Z0-9/_-]*[a-zA-Z/_-][a-zA-Z0-9/_-]*)+

This also obeys the restriction that tags cannot be only numbers. The astute reader will notice that this allows for an all-number sub-tag, or empty tag. Yes, it does, because Obsidian recognizes them as tags, so Obsidian will actually accept and tag crazy things like:

#///777/

So I’ve gotta conform, if I expect external results to match internal (Obsidian) results.

The only hiccup is that the regex will capture leading space, which isn’t really a part of the tag, but that’s easily “strippable.” I wanted to do a Positive Lookbehind but that’s not reliable in a cross-platform or cross-tool context, so it has to be avoided. Also, the sequence

(^|[[:blank:]])

should be simplified to

[[:space:]]

except that it’s not picking up tags at beginning of line, even though it should.
Linux man page citation: grep → re_format → wctype → isspace

Edit: Whoops, I forgot to handle the case with the pipe. Rather than delete the post I’ll update it later.

Edit2: Regex not rendering properly due to display interpretation; fixed. I’m addressing the pipe issue in a followup post.

Edit3: Oof. Yet another display rendering issue. Hopefully the last one. This getting kinda meta.