Nim: Finding & extracting substrings

Mar 21, 2022

Much like in Ruby, Nim treats strings as a sequence of chars. This means if you already know the positional value of the substring you want to access you can access it like an array (zero indexed):

var a = "Hello World!"
echo a[0]
# H

It also means you can supply a range to access more than a single char, having a slice returned:

var a = "Hello World!"
echo a[0 .. 4]
# Hello

In JavaScript/ECMAScript to work backwards from the end of the string means first determining the length of the string, which is also possible in Nim by calling len(str). However the recommended way to do it is using the ^ operator which is interpreted by the compile as the same thing, e.g.:

var a = "Hello World!"
echo a[0 .. ^1]
# Hello World!
# i.e., the whole strong

echo a[0 .. ^2]
# Hello World

echo a[^6 .. ^2]
# World

To check if a string contains a substring:

import strutils
var str = "Hello World!"
echo str.contains("World")
# true

To find the positional location of a substring:

import strutils
var str = "Hello World!"
echo str.find("World")
# 6

More advanced matching is possible via the std/strscans import. This is handly when you might ordinarily want to reach for regex, but want something a little more readable and expressive of intent. For example, this will extract integers that match the (int, int, int) format:

const input = "(1,2,4)"
var x, y, z: int
if scanf(input, "($i,$i,$i)", x, y, z):
  echo "matches and x is ", x, " y is ", y, " z is ", z
# matches and x is 1 y is 2 z is 4

Rather than instantiating those variables it's also possible to use scanTuple to return a tuple of values:

let (success, year, month, day, time) = scanTuple("1000-01-01 00:00:00", "$i-$i-$i$s$+")
if success:
  assert year == 1000
  assert month == 1
  assert day == 1
  assert time == "00:00:00"

If you do need the power of regular expressions the std/re gives you access to the functions you'd expect:

import std/re
var matches: array[2, string]
if match("abcdefg", re"c(d)ef(g)", matches, 2):
  echo matches
  # ["d", "g"]
Hi, I'm Glenn! 👋 I'm currently Director of Product (Terraform) @ HashiCorp, and we're hiring! If you'd like to come and work with me and help make Terraform Cloud even more amazing we have multiple positions opening in Product ManagementDesign, and Engineering & Engineering Management across a range of levels (i.e., junior through to senior). Please send in an application ASAP so we can get in touch.