2016-07-27 4 views
1

Ich lerne Golang, damit ich einige meiner Shell-Skripte umschreiben kann.Teil der Zeichenfolge in Golang extrahieren?

Ich habe URLs, die diese wie folgt aussehen:

https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value 

ich folgende Teil extrahieren möchten:

https://example-1.example.com/a/c482dfad3573acff324c/list.txt 

In einem Shell-Skript würde ich so etwas tun:

echo "$myString" | grep -o 'http://.*.txt' 

Was ist der beste Weg, das gleiche in Golang zu tun, nur mit der Standard-Bibliothek?

Antwort

6

Es gibt ein paar Optionen:

// match regexp as in question 
pat := regexp.MustCompile(`https?://.*\.txt`) 
s := pat.FindString(myString) 

// everything before the query 
s := strings.Split(myString, "?")[0] string 

// same as previous, but avoids []string allocation 
s := myString 
if i := strings.IndexByte(s, '?'); i >= 0 { 
    s = s[:i] 
} 

// parse and clear query string 
u, err := url.Parse(myString) 
u.RawQuery = "" 
s := u.String() 

Die letzte Option ist die beste, weil es alle möglichen Sonderfälle behandelt.

try it on the playground

+0

Id empfehlen die Verwendung von url.Parse da dass jede seltsame Grenzfälle behandeln soll was durch eine Regex oder einen Split verpasst werden könnte. Zum Beispiel URLs ohne? –

+0

Ich stimme zu, dass url.Parse der beste Ansatz ist. Alle aufgeführten Optionen behandeln URLs ohne ein '?'. –

1

können Sie strings.IndexRune, strings.IndexByte, strings.Split, strings.SplitAfter, strings.FieldsFunc, url.Parse, regexp oder Ihre Funktion verwenden.

erste einfachste Weg:
Sie i := strings.IndexRune(s, '?') oder i := strings.IndexByte(s, '?') dann s[:i] wie folgt aus (mit kommentierten Ausgabe) verwenden:

package main 

import "fmt" 
import "strings" 

func main() { 
    s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value` 
    i := strings.IndexByte(s, '?') 
    if i != -1 { 
     fmt.Println(s[:i]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt 
    } 
} 

oder Sie verwenden url.Parse(s) (ich dies verwenden würde):

package main 

import "fmt" 
import "net/url" 

func main() { 
    s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value` 
    url, err := url.Parse(s) 
    if err == nil { 
     url.RawQuery = "" 
     fmt.Println(url.String()) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt 
    } 
} 

oder Sie verwenden regexp.MustCompile(".*\\.txt"):

package main 

import "fmt" 
import "regexp" 

var rgx = regexp.MustCompile(`.*\.txt`) 

func main() { 
    s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value` 

    fmt.Println(rgx.FindString(s)) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt 
} 

oder können Sie splits := strings.FieldsFunc(s, func(r rune) bool { return r == '?' }) dann splits[0] verwenden:

package main 

import "fmt" 
import "strings" 

func main() { 
    s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value` 
    splits := strings.Split(s, "?") 
    fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt 
} 

Sie splits := strings.SplitAfter(s, ".txt") dann splits[0] verwenden:

package main 

import "fmt" 
import "strings" 

func main() { 
    s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value` 
    splits := strings.SplitAfter(s, ".txt") 
    fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt 
} 

oder Sie können

package main 

import "fmt" 
import "strings" 

func main() { 
    s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value` 
    splits := strings.FieldsFunc(s, func(r rune) bool { return r == '?' }) 
    fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt 
} 

Sie splits := strings.Split(s, "?") dann splits[0] verwenden nutze deine Funktion (selbständigste Fahrt):

package main 

import "fmt" 

func left(s string) string { 
    for i, r := range s { 
     if r == '?' { 
      return s[:i] 
     } 
    } 
    return "" 
} 

func main() { 
    s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value` 
    fmt.Println(left(s)) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt 
} 
1

Wenn Sie nur URLs prosessing, können Sie net/url Bibliothek Gos verwenden https://golang.org/pkg/net/url/ die URL zu analysieren, um die Abfrage und Fragment Teile gestutzt (Query wäre parm1=value,parm2=value usw.), Und Extrahieren des verbleibenden Teils scheme://host/path, wie in dem folgenden Beispiel (https://play.golang.org/p/Ao0jU22NyA):

package main 

import (
    "fmt" 
    "net/url" 
) 

func main() { 
    u, _ := url.Parse("https://example-1.example.com/a/b/c/list.txt?parm1=value,parm2=https%3A%2F%2Fexample.com%2Fa%3Fparm1%3Dvalue%2Cparm2%3Dvalue#somefragment") 
    u.RawQuery, u.Fragment = "", "" 
    fmt.Printf("%s\n", u) 
} 

Output:

https://example-1.example.com/a/b/c/list.txt