为什么'\'在这个用os/exec调用的命令中无效?
Why is '\' invalid in this command called with os/exec?
当我执行这段用 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)
从我的 shell(我使用 Bash)执行的 和 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=\"/"
也工作正常。
为什么我不能在我的 Go 代码中完成同样的事情?我该如何解决这个问题?
P.S。此处粘贴的只是较长程序的片段。
在一种语言中转义引号很难。尽可能使用替代语法来减轻这种痛苦。
您的语法很复杂,因为您选择用双引号将字符串引起来,但字符串包含双引号,因此必须对它们进行转义。此外,字符串中有双引号,它们本身必须被转义。你已经逃脱了他们,但最后在你的转义中打了一个字:
"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 中适当使用单引号来描述文字字符串
最好不要 shell 出去,除非你真的必须
你在这里的所有痛苦都是因为你采用了在 bash 中有效的代码,并试图将其封装在另一种编程语言中。除非你真的必须这样做,否则不要这样做。
在这里考虑一个可能会让你的生活更轻松的替代方案:
使用 Go 的 net/http
库而不是 wget
.
发出 http 请求
用https://pkg.go.dev/golang.org/x/net/html解析响应中的HTML,这将比grep
更健壮。 HTML 内容没有很好地 grep。
当我执行这段用 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)
从我的 shell(我使用 Bash)执行的 和 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=\"/"
也工作正常。
为什么我不能在我的 Go 代码中完成同样的事情?我该如何解决这个问题?
P.S。此处粘贴的只是较长程序的片段。
在一种语言中转义引号很难。尽可能使用替代语法来减轻这种痛苦。
您的语法很复杂,因为您选择用双引号将字符串引起来,但字符串包含双引号,因此必须对它们进行转义。此外,字符串中有双引号,它们本身必须被转义。你已经逃脱了他们,但最后在你的转义中打了一个字:
"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 中适当使用单引号来描述文字字符串
最好不要 shell 出去,除非你真的必须
你在这里的所有痛苦都是因为你采用了在 bash 中有效的代码,并试图将其封装在另一种编程语言中。除非你真的必须这样做,否则不要这样做。
在这里考虑一个可能会让你的生活更轻松的替代方案:
使用 Go 的
发出 http 请求net/http
库而不是wget
.用https://pkg.go.dev/golang.org/x/net/html解析响应中的HTML,这将比
grep
更健壮。 HTML 内容没有很好地 grep。