regex – How to select first chars with a custom word boundary?-ThrowExceptions

Exception or error:

I’ve test cases with a series of words like this :

    {
        input:    "Halley's Comet",
        expected: "HC",
    },
    {
        input:    "First In, First Out",
        expected: "FIFO",
    },
    {
        input:    "The Road _Not_ Taken",
        expected: "TRNT",
    },

I want with one regex to match all first letters of these words, avoid char: “_” to be matched as a first letter and count single quote in the word.
Currently, I have this regex working on pcre syntax but not with Go regexp package : (?<![a-zA-Z0-9'])([a-zA-Z0-9'])
I know lookarounds aren’t supported by Go but I’m looking for a good way to do that.

I also use this func to get an array of all strings : re.FindAllString(s, -1)

Thanks for helping.

How to solve:

Something that plays with character classes and word boundaries should suffice:

\b_*([a-z])[a-z]*(?:'s)?_*\b\W*

demo

Usage:

package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(?i)\b_*([a-z])[a-z]*(?:'s)?_*\b\W*`)
    fmt.Println(re.ReplaceAllString("O'Brian's dog", "$1"))

}

Answer:

ftr, regexp less solution

package main

import (
    "fmt"
)

func main() {
    inputs := []string{"Hallمرحباey's Comet", "First In, First Out", "The Road _Not_ Taken", "O'Brian's Dog"}
    c := [][]string{}
    w := [][]string{}
    for _, input := range inputs {
        c = append(c, firstLet(input))
        w = append(w, words(input))
    }
    fmt.Printf("%#v\n", w)
    fmt.Printf("%#v\n", c)
}

func firstLet(in string) (out []string) {
    var inword bool
    for _, r := range in {
        if !inword {
            if isChar(r) {
                inword = true
                out = append(out, string(r))
            }
        } else if r == ' ' {
            inword = false
        }
    }
    return out
}

func words(in string) (out []string) {
    var inword bool
    var w []rune
    for _, r := range in {
        if !inword {
            if isChar(r) {
                w = append(w, r)
                inword = true
            }
        } else if r == ' ' {
            if len(w) > 0 {
                out = append(out, string(w))
                w = w[:0]
            }
            inword = false
        } else if r != '_' {
            w = append(w, r)
        }
    }
    if len(w) > 0 {
        out = append(out, string(w))
    }
    return out
}

func isChar(r rune) bool {
    return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z')
}

outputs

[][]string{[]string{"Hallمرحباey's", "Comet"}, []string{"First", "In,", "First", "Out"}, []string{"The", "Road", "Not", "Taken"}, []string{"O'Brian's", "Dog"}}
[][]string{[]string{"H", "C"}, []string{"F", "I", "F", "O"}, []string{"T", "R", "N", "T"}, []string{"O", "D"}}

Leave a Reply

Your email address will not be published. Required fields are marked *