regexp(n)

πŸ“¦
version 9.0.3 Β· 2 versions
, in alpine 3.23, alpine 3.24, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable

πŸ’– regexp(n) β€” the Tcl Built-In Commands girlie πŸ’–

okay bestie, buckle up, we're doing regular expressions today and honestly? it's giving main character energy. this is the regexp manual page, and by the end of it you're gonna be matching patterns like it's nothing. periodt.


✨ NAME ✨

regexp β€” match a regular expression against a string πŸ¦‹


✨ SYNOPSIS ✨

regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?

✨ DESCRIPTION ✨

so the whole vibe here: this command figures out whether the regular expression exp matches part or all of string. it returns 1 if it does and 0 if it does not β€” unless you threw -inline in there, in which case it's a whole different story (keep reading, we get to it πŸ’…).

(if you wanna know how the regex matching itself actually works, that's a whole separate manual page β€” go look at the re_syntax reference page, she's the blueprint ✨)

okay so if you pass extra arguments after string, those get treated as the names of variables where we're gonna drop info about which part(s) of string matched exp. here's the tea:

  • matchVar gets set to the range of string that matched all of exp β€” the whole match, no crumbs left behind πŸ‘‘
  • the first subMatchVar gets the characters in string that matched the leftmost parenthesized subexpression inside exp
  • the next subMatchVar gets the characters that matched the next parenthesized subexpression to the right in exp
  • and so on and so on, down the line 🌈

now: if the initial arguments to regexp start with -, they get treated as switches. here's the full roster, no skips, no cuts:

πŸŽ€ OPTIONS πŸŽ€

  • -about β€” instead of even trying to match the regex, this returns a list of info about the regular expression itself. first element of the list = a subexpression count. second element = a list of property names describing various attributes of the regex. this one is primarily for debugging purposes, iykyk πŸ›
  • -expanded β€” turns on the expanded regular expression syntax, where whitespace and comments are just... ignored, like they're not even there πŸ™ˆ. this is the same as specifying the (?x) embedded option (see the re_syntax manual page).
  • -indices β€” changes what gets stored in the matchVar and subMatchVars. instead of storing the matching characters from string, each variable gets a list of two decimal strings giving the indices in string of the first and last characters in the matching range. coordinates, not content, bestie πŸ“
  • -line β€” enables newline-sensitive matching. by default, newline is a completely ordinary character with no special meaning, no drama, nothing. but with this flag: [^ bracket expressions and . never match newline, ^ matches an empty string after any newline in addition to its normal function, and $ matches an empty string before any newline in addition to its normal function. this flag is equivalent to specifying both -linestop and -lineanchor, or the (?n) embedded option (see the re_syntax manual page). it's the combo meal πŸ”
  • -linestop β€” changes the behavior of [^ bracket expressions and . so they stop at newlines. same as specifying the (?p) embedded option (see the re_syntax manual page).
  • -lineanchor β€” changes the behavior of ^ and $ (the "anchors") so they match the beginning and end of a line respectively. same as specifying the (?w) embedded option (see the re_syntax manual page). anchors, but make it line-aware βš“
  • -nocase β€” causes upper-case characters in string to be treated as lower case during the matching process. we do not care about your capital letters here πŸ’…
  • -all β€” causes the regular expression to be matched as many times as possible in the string, and returns the total number of matches found. and heads up: if you use this with match variables, those variables will only contain info for the last match. only the last one. don't say I didn't warn you 😭
  • -inline β€” causes the command to return, as a list, the data that would otherwise be placed in match variables. when you're using -inline, match variables may not be specified, so pick a lane bestie 🫢. if used with -all, the list gets concatenated at each iteration, such that a flat list is always returned. for each match iteration, the command appends the overall match data, plus one element for each subexpression in the regular expression. examples, because seeing it >> reading it:
regexp -inline -- {\w(\w)} " inlined "
      β†’ in n
regexp -all -inline -- {\w(\w)} " inlined "
      β†’ in n li i ne e
  • -start index β€” specifies a character index offset into the string to start matching the regular expression at. the index value is interpreted in the same manner as the index argument to string index. when you use this switch, ^ will not match the beginning of the line, and \A will still match the start of the string at index. if -indices is specified, the indices will be indexed starting from the absolute beginning of the input string. and index gets constrained to the bounds of the input string β€” no wandering off 🚧
  • -- β€” marks the end of switches. the argument following this one will be treated as exp even if it starts with a -. the escape hatch, the safety net, the "not me getting into an argument with my own flags" moment πŸ™ˆ

πŸ¦‹ the empty-match tea πŸ¦‹

if there are more subMatchVars than there are parenthesized subexpressions within exp, or if a particular subexpression in exp does not match the string (like, for example, because it was in a portion of the expression that wasn't matched at all), then the corresponding subMatchVar gets set to:

  • -1 -1 if -indices has been specified, or
  • an empty string otherwise

no match, no content, that's the rule πŸŽ€


🌸 EXAMPLES 🌸

1. find the first occurrence of a word starting with foo in a string that is not actually an instance of foobar, and grab the letters following it up to the end of the word into a variable:

regexp {\mfoo(?!bar\M)(\w*)} $string -> restOfWord

and note: the whole matched substring got placed in the variable ->, which is a name chosen to look nice given that we're not actually interested in its contents. it's decorative, it's aesthetic, it's -> πŸ’…

2. find the index of the word badger (in any case) within a string and store it in the variable location:

regexp -indices {(?i)\mbadger\M} $string location

3. this could also be written as a basic regular expression match (as opposed to using the default syntax of advanced regular expressions) by prefixing the expression with a suitable flag:

regexp -indices {(?ib)\<badger\>} $string location

4. this counts the number of octal digits in a string:

regexp -all {[0-7]} $string

5. this lists all words (consisting of all sequences of non-whitespace characters) in a string, and is useful as a more powerful version of the split command:

regexp -all -inline {\S+} $string

πŸ‘‘ SEE ALSO πŸ‘‘

re_syntax(n), regsub(n), string(n) β€” go read these next, they're the friend group 🌈


⭐ KEYWORDS ⭐

match, parsing, pattern, regular expression, splitting, string


and that's the whole page, bestie!! no notes, no skips, every flag accounted for πŸ’œ this was Tcl 8.3, and honestly? iconic behavior. now go match some patterns, you absolute regexp girlie πŸ¦‹βœ¨πŸ’–

πŸ“¦ where this page comes from