为什么是'\'使用 os/exec 调用的命令无效?

发布于 2025-01-09 12:57:46 字数 1975 浏览 0 评论 0原文

当我执行用 Go 编写的这段代码时:

package main

import ( "fmt" 
"os/exec"
)

func donde(num string) string {                                                                                                                                                         
  cmd := fmt.Sprintf("wget -qO- \"https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18&edadh=30\"|grep -av \"https:\"|grep -av \"contactos\"|grep -av \"javascript\"|grep -av \"href=\\"/\"", num)
  out, err := exec.Command("bash","-c",cmd).Output()
        if err != nil {
                return fmt.Sprintf("Failed to execute command: %s", cmd)
        }
        return string(out)
}

func main() {

chicas := map[string][]string{ "Alexia":{"600080000"}, 
"Paola":{"600070008", "600050007", "600000005", "600000001", "600004", "600000000"}}    

for k, v := range chicas { 
    fmt.Printf("%s\n", k)
    for index := range v {
        c := donde(v[index])
        exec.Command("bash", "-c", c)
        fmt.Println(c)}

  }
    
}

我得到:

./favoritas.go:8:189: invalid operation: "wget -qO- \"https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18... / "" (operator / not defined on untyped string)
./favoritas.go:8:190: invalid character U+005C '\'

grep -av \"href=\\"/\" 似乎是罪魁祸首。有趣的是,类似的 Python 代码 工作得很好:

from subprocess import run
v = "600000005"
dnd = run('wget -qO- \"https://www.pasion.com/contactos-mujeres/'+v+'.htm?edadd=18&edadh=30\" |grep -av \"https:\"|grep -av \"contactos\"|grep -av \"javascript\" |grep -av \"href=\\"/\"' , capture_output=True, shell=True, text=True, encoding='latin-1').stdout
print(dnd)

wget -qO- "https://www.pasion.com/contactos-mujeres/600000003.htm?edadd=18&edadh=30" |grep -av "https:"|grep -从我的 shell(我使用 Bash)执行的 av "contactos"|grep -av "javascript" |grep -av "href=\"/" 也可以正常工作。 为什么我不能在 Go 代码中完成同样的任务?我该如何解决这个问题?

PS 这里粘贴的只是较长程序的片段。

When I execute this code written in Go:

package main

import ( "fmt" 
"os/exec"
)

func donde(num string) string {                                                                                                                                                         
  cmd := fmt.Sprintf("wget -qO- \"https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18&edadh=30\"|grep -av \"https:\"|grep -av \"contactos\"|grep -av \"javascript\"|grep -av \"href=\\"/\"", num)
  out, err := exec.Command("bash","-c",cmd).Output()
        if err != nil {
                return fmt.Sprintf("Failed to execute command: %s", cmd)
        }
        return string(out)
}

func main() {

chicas := map[string][]string{ "Alexia":{"600080000"}, 
"Paola":{"600070008", "600050007", "600000005", "600000001", "600004", "600000000"}}    

for k, v := range chicas { 
    fmt.Printf("%s\n", k)
    for index := range v {
        c := donde(v[index])
        exec.Command("bash", "-c", c)
        fmt.Println(c)}

  }
    
}

I get:

./favoritas.go:8:189: invalid operation: "wget -qO- \"https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18... / "" (operator / not defined on untyped string)
./favoritas.go:8:190: invalid character U+005C '\'

grep -av \"href=\\"/\" seems to be the culprit. Interestingly, similar Python code
works just fine:

from subprocess import run
v = "600000005"
dnd = run('wget -qO- \"https://www.pasion.com/contactos-mujeres/'+v+'.htm?edadd=18&edadh=30\" |grep -av \"https:\"|grep -av \"contactos\"|grep -av \"javascript\" |grep -av \"href=\\"/\"' , capture_output=True, shell=True, text=True, encoding='latin-1').stdout
print(dnd)

and wget -qO- "https://www.pasion.com/contactos-mujeres/600000003.htm?edadd=18&edadh=30" |grep -av "https:"|grep -av "contactos"|grep -av "javascript" |grep -av "href=\"/" executed from my shell (I use Bash) works fine as well.
Why cannot I accomplish the same in my code Go? How might I resolve this issue?

P.S. What is pasted here are just snippets of more lengthy programs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

为人所爱 2025-01-16 12:57:46

在一种语言中转义一种语言中的引号是很困难的。使用可用的替代语法来减轻这种痛苦。

您的语法很复杂,因为您选择用双引号将字符串引起来,但字符串包含双引号,因此必须对它们进行转义。此外,字符串中的双引号本身必须转义。您已经转义了它们,但在最后的转义中进行了打字:

"wget -qO- \"https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18&edadh=30\"|grep -av \"https:\"|grep -av \"contactos\"|grep -av \"javascript\"|grep -av \"href=\\"/\""

您转义了反斜杠,但没有包含额外的反斜杠来转义引号。这样引用的字符串就结束了。 / 未在字符串中加引号,因此作为运算符应用于加引号的字符串。但是 string 没有 / 运算符,因此会出现错误。

`wget -qO- "https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18&edadh=30"|grep -av "https:"|grep -av "contactos"|grep -av "javascript"|grep -av 'href="/'`

关键点:在适当的时候使用反引号来引用包含引号的字符串,这样您就不需要在字符串中转义引号。

此外,如果您在 bash 中使用单引号,它将禁用所有特殊字符,直到找到另一个单引号。 grep -av 'href="/' 更简单,不是吗?

关键要点:在适当的时候在 bash 中使用单引号来描述文字字符串

更好的是,不要'除非你真的不得不

这样做,否则不要这么做,因为你采用了 bash 中有效的代码,并试图将其封装在另一种编程语言中,除非你真的必须

考虑使用替代方案 。让你的生活更轻松:

escaping quotes within a language within a language is hard. Use alternate syntax when available to alleviate this pain.

Your syntax is complex because you chose to enquote the string with double quotes, but the string contains double quotes, so they must be escaped. Additionally, you have double quotes within the string that themselves must be escaped. You've escaped them, but made a typeo in your escaping at the end:

"wget -qO- \"https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18&edadh=30\"|grep -av \"https:\"|grep -av \"contactos\"|grep -av \"javascript\"|grep -av \"href=\\"/\""

you escaped the backslash, but did not include an additional backslash to escape the quote. So the quoted string ended. The / is not enquoted in the string, thus applied to the quoted string as an operator. But string has no / operator, hence the error.

`wget -qO- "https://www.pasion.com/contactos-mujeres/%s.htm?edadd=18&edadh=30"|grep -av "https:"|grep -av "contactos"|grep -av "javascript"|grep -av 'href="/'`

key takeaway: use backticks when appropriate to enquote strings that contain quotes, then you won't need to escape quotes within the string.

additionally, if you use single quote in bash, it will disable all special characters until another single quote is found. grep -av 'href="/' is more straightforward, no?

key takeaway: use single quotes in bash, when appropriate, to delineate literal strings

Better yet, don't shell out unless you really have to

all your pain here is because you took code that was valid in bash, and tried to encapsulate it within another programming language. don't do that unless you really have to.

consider an alternative here that might make your life easier:

  • Make the http request with Go's net/http library instead of wget.

  • Parse the HTML in the response with https://pkg.go.dev/golang.org/x/net/html which will be more robust than grep. HTML content does not grep well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文