-1

I have a string that could have a -name followed by value (that can have spaces) and there could also be -descr after that followed by a value (the -descr followed by value may nor may not be there):

Example strings:

runcmd -name abcd xyz -descr abc def

or

runcmd -name abcd xyz

With Go language, how do I write regexp, that returns me the string before -descr if it exists. so, for both examples above, the result should be:

runcmd -name abcd xyz

I was trying:

regexp.MustCompile(`(-name ).+?=-descr`)

But, that did not return any match. I wanted to know the correct regexp to get the string up until -descr if it exists

user1892775
  • 2,001
  • 6
  • 37
  • 58

3 Answers3

1

You could capturin first part with -name in a group, then match what is in between and use an optional second capturing group to match -descr and what follows.

Then you could use the capturing groups when creating the desired result.

^(.*? -name\b).*?(-descr\b.*)?$

Regex demo | Go demo

For example:

s := "runcmd -name abcd xyz -descr abc def"
re1 := regexp.MustCompile(`^(.*? -name\b).*?(-descr\b.*)?$`)
result := re1.FindStringSubmatch(s)
fmt.Printf(result[1] + "..." + result[2])

Result:

runcmd -name...-descr abc def
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • Is it possible to modify this so the first group only contains uptil -name? The reason is, I would eventually need to do something like re1.ReplaceAllString(s, "$1"+"...."+" ")), so I can return the original string just with the value of -name replaced with ...., so the output string becomes `runcmd -name .... -descr abc def` which is the final goal – user1892775 Jan 09 '19 at 22:18
  • @user1892775 To get only the first group you could use `^(.*? -name)` [demo](https://regex101.com/r/ojNnBl/2). In that case you could also use just a match instead `^.*? -name` [demo](https://regex101.com/r/ojNnBl/1) and it could look like this [Go demo](https://ideone.com/GScvjs) – The fourth bird Jan 09 '19 at 22:21
  • Not sure, if I was clear enough, I want to modify the regexp so that s := "runcmd -name abcd xyz -descr abc def" re1 := regexp.MustCompile(regexp) fmt.Println(re1.ReplaceAllString(s, "$1"+"...."+" ")) should be `runcmd -name .... -descr abc def' – user1892775 Jan 09 '19 at 22:32
  • If you could share an example which would give that output (the string with value for -name replaced with ....) as indicated in the code above, that would really help – user1892775 Jan 09 '19 at 22:35
  • @user1892775 Do you mean like this using 2 capturing groups? https://ideone.com/vOTdLz – The fourth bird Jan 09 '19 at 22:48
  • Sorry if its getting confusing. Let me try to make it simpler. For inputstr = "runcmd -name abcd xyz -descr abc def", I want the output to be "runcmd -name .... -descr abc def" – user1892775 Jan 09 '19 at 22:55
  • @user1892775 You could concatenate the groups https://ideone.com/aHwa3L – The fourth bird Jan 09 '19 at 22:58
  • yeah, but then it seem to fail for the inputstr s = "runcmd -name abcd xyz" (that is, when -descr option is missing) – user1892775 Jan 09 '19 at 23:08
  • @user1892775 In that case you can make the second capturing group optional https://ideone.com/V6bGpF – The fourth bird Jan 09 '19 at 23:17
  • @user1892775 I have updated my answer with the latest example. – The fourth bird Jan 09 '19 at 23:25
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/186440/discussion-between-user1892775-and-the-fourth-bird). – user1892775 Jan 10 '19 at 03:46
0

By "Does not work", do you mean it doesn't match anything, or just not what you expect?

https://regex101.com/ is generally very helpful when testing regular expressions.

I do not believe there's a simple way to achieve what you want. Things become a lot simpler if we can assume the text betweeen -name and -descr doesn't contain any - in which case, regex.MustCompile(`-name ([^-]*)`) should work

With this kind of thing, often it's easier and clearer to use 2 regular expressions. So the first strips -descr and anything following it, and the first matches -name and all subsequent characters.

Stuart Moore
  • 681
  • 5
  • 32
0

You are not dealing with a regular language here, so there is no reason to bust out the (slow) regexp engine. The strings package is quite enough:

package main

import (
    "fmt"
    "strings"
    "unicode"
)

func main() {
    fmt.Printf("%q\n", f("runcmd -name abcd xyz -descr abc def"))
    fmt.Printf("%q\n", f("runcmd -name abcd xyz"))
    fmt.Printf("%q\n", f("-descr abc def"))
}

func f(s string) string {
    if n := strings.Index(s, "-descr"); n >= 0 {
        return strings.TrimRightFunc(s[:n], unicode.IsSpace)
    }
    return s
}

// Output:
// "runcmd -name abcd xyz"
// "runcmd -name abcd xyz"
// ""

Try it on the playground: https://play.golang.org/p/RFC65CYe6mp

Peter
  • 29,454
  • 5
  • 48
  • 60