At the core, a tag is just an ordered combination of two UTF-8 text strings, each with a max length of 255 (not 256) Unicode characters (not bytes). Keys of tags on an element must all be unique. [is there a limit on how many tags?] [could the old segments have tags?]
They are commonly represented in the format
Note that it is possible to have an equals sign in the key and value, but this is almost always an error. The same applies to leading/trailing white-space.
There are many cases where you may need to have multiple values, or a list of values for a tag. Depending on the lists meaning, and whether it can have sub-lists, there are different ways to create them.
The semicolon is the standard separator for lists in OSM, probably due to it being a normal list seperator, and being less likely to be part of a name than a
The comma is sometimes used instead of a semicolon in tags, however many of these tags have moved to a semicolon. It is also sometimes used by mistake instead of another seperator.
The pipe is used for list of values that differ per-lane and those values can have sub-lists with a semicolon. See #:lanes
It is also used for free-form text values as a replacement for a new-line. Whilst using a new-line in a tag value is possible, it is generally seen as a bad thing to use control characters in tags. JOSM doesn't support entering new-lines in tags and the text-box may behave oddly if there are some present.