在Golang中执行find命令并使用正则表达式匹配。

huangapple go评论82阅读模式
英文:

golang exec find command regex

问题

我正在尝试在Go语言中编写一个find命令(下面是Shell命令):

find . -mindepth 3 -maxdepth 3 -regex '.*\(type-a\|type-b\)\/os.*'

以下是Go代码片段:

package main

import (
    "bytes"
    "fmt"
    "os/exec"
)

func main() {

    cmd := exec.Command("/usr/bin/find", "/opt/system/versions",
                        "-mindepth",  "3", "-maxdepth",  "3",
                        "-regex",  ".*(type-a|type-b)/os.*")

    var out bytes.Buffer
    var stderr bytes.Buffer
    cmd.Stdout = &out
    cmd.Stderr = &stderr

    err:= cmd.Run()
    if err != nil {
        fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
        return
    }
    fmt.Println("Directory contents: ", out.String())
}

如果我只搜索type-a(或只搜索type-b),它可以正常工作。但是,当我搜索type-atype-b时(Shell命令可以正常工作),它就无法正常工作。我在传递给Command的正则表达式模式中出了什么问题?

当我使用\转义(|)时,Go会报错说unknown escape sequence: (

cmd := exec.Command("/usr/bin/find", "/opt/system/versions",
                    "-mindepth",  "3", "-maxdepth",  "3",
                    "-regex",  ".*\\(type-a\\|type-b\\)/os.*")

请帮我看看我在正则表达式模式中做错了什么。

英文:

I am trying to write a find command (shell command below) in go:

find . -mindepth 3 -maxdepth 3 -regex '.*\(type-a\|type-b\)\/os.*'

Here is the go snippet:

package main

import (
    "bytes"
    "fmt"
    "os/exec"
)

func main() {

    cmd := exec.Command("/usr/bin/find", "/opt/system/versions",
                        "-mindepth",  "3", "-maxdepth",  "3",
                        "-regex",  ".*(type-a|type-b)/os.*")

    var out bytes.Buffer
    var stderr bytes.Buffer
    cmd.Stdout = &out
    cmd.Stderr = &stderr

    err:= cmd.Run()
    if err != nil {
        fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
        return
    }
    fmt.Println("Directory contents : ", out.String())
}

It works fine if I search for just type-a (or just type-b). Does not work when I search for either type-a or type-b (the shell command works just fine). What did I get wrong in the regex pattern fed into Command?

When I escape the (, | and ) using \ , go complains about the escape sequence - unknown escape sequence: (:

    cmd := exec.Command("/usr/bin/find", "/opt/system/versions",
                        "-mindepth",  "3", "-maxdepth",  "3",
                        "-regex",  ".*\(type-a\|type-b\)/os.*")

答案1

得分: 2

默认情况下,find 命令将正则表达式解释为 Emacs 正则表达式,其中,特别地,选择操作符是 \|,分组操作使用反斜杠后跟括号 \(\). 因此,你应该使用正确的 Emacs 正则表达式语法,或者使用 -regextype 选项来使用替代的正则表达式语法,其中这些操作符不需要前缀反斜杠,例如:

find -regextype 'posix-extended' -regex '.*(type-a|type-b)/os.*';

由于在 Go 语言中反斜杠被用作字符串中的转义字符,你应该使用额外的反斜杠来转义反斜杠字符本身,例如:

cmd := exec.Command("/usr/bin/find", "/opt/system/versions",
                    "-mindepth", "3", "-maxdepth", "3",
                    "-regex", ".*\\(type-a\\|type-b\\)\\/os.*")
英文:

By default, find interprets regular expressions as Emacs Regular Expressions, where, particularly, the alteration operator is \|, and grouping is performed with backslashes followed by parentheses \(, \). So you should either use the correct Emacs Regular Expressions syntax, or use alternative regular expressions syntax with the help of -regextype option, where these operators are not prefixed with backslashes, e.g.:

find -regextype 'posix-extended' -regex '.*(type-a|type-b)/os.*'

Since backslash in Go is used as an escape character in strings, you should escape the backslash character itself with an extra backslash, e.g.:

cmd := exec.Command("/usr/bin/find", "/opt/system/versions",
                    "-mindepth",  "3", "-maxdepth",  "3",
                    "-regex",  ".*\\(type-a\\|type-b\\)\\/os.*")

huangapple
  • 本文由 发表于 2017年9月13日 10:08:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/46187770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定