英文:
How to ignore extra fields for fmt.Sprintf
问题
我有一个使用 Golang 编写的程序,它从命令行读取一个字符串参数,并将其传递给 fmt.Sprintf 函数。假设 tmp_str 是来自命令行的目标字符串。
在某些情况下,程序会传递一个完整的字符串,比如 "Hello Friends",而不是一个字符串模板。程序会发生 panic 并返回以下内容:
Hello Friends%!(EXTRA string=world)
那么,如何忽略 fmt.Sprintf 中的额外字段呢?
英文:
I have a Golang program that reads a string parameter from command line and passes it to the fmt.Sprintf function. Let's say tmp_str is the target string from command line.
package main
import "fmt"
func main() {
tmp_str := "hello %s"
str := fmt.Sprintf(tmp_str, "world")
fmt.Println(str)
}
In some cases, the program will pass a completed string like "Hello Friends", instead of a string template.. The program would panic and return:
> Hello Friends%!(EXTRA string=world)
So, how to ignore the extra fields for fmt.Sprintf?
答案1
得分: 9
是的,你可以通过对传递给可变参数的Sprintf
函数的参数进行切片来实现:
func TruncatingSprintf(str string, args ...interface{}) (string, error) {
n := strings.Count(str, "%s")
if n > len(args) {
return "", errors.New("Unexpected string:" + str)
}
return fmt.Sprintf(str, args[:n]...), nil
}
func main() {
tmp_str := "hello %s %s %s" // 在这里可以添加很多%s
str, err := TruncatingSprintf(tmp_str, "world") // 或者在这里添加很多参数
if err != nil {
fmt.Println(err)
return
}
fmt.Println(str)
}
演示2(当有更多的%s比参数时,输出不同版本)
但是通常情况下,你不会使用动态格式化的字符串,这不安全,如果你想接受任意字符串,你还应该修改这段代码,以便不会因为%%s
而出错。如果你想走得更远,那么你可能应该看一下模板(它允许你使用命名字符串,因此缺失的字符串不必是最后一个)。
英文:
Yes you can do it, by slicing the arguments you pass to the variadic Sprintf
function:
func TruncatingSprintf(str string, args ...interface{}) (string, error) {
n := strings.Count(str, "%s")
if n > len(args) {
return "", errors.New("Unexpected string:" + str)
}
return fmt.Sprintf(str, args[:n]...), nil
}
func main() {
tmp_str := "hello %s %s %s" // don't hesitate to add many %s here
str, err := TruncatingSprintf(tmp_str, "world") // or many arguments here
if err != nil {
fmt.Println(err)
return
}
fmt.Println(str)
}
Demonstration 2 (a different version outputting even when there's more %s than arguments)
But you don't usually use dynamic formatted strings, this isn't secure and if you want to accept any string, you should also adapt this code to no choke on %%s
. If you venture this far, then you should probably have a look at templates (which would let you use named strings, and thus the missing one wouldn't have to be the last one).
答案2
得分: 8
在这种特殊情况下,你可以要求命令行用户始终提供一个%s动词,并解释他们可以将字符串截断为零长度:
你好朋友%.0s
甚至更短:
你好朋友%.s
输出结果是简单的:
你好朋友
英文:
In this particular case, you could require the command line users to always supply a %s verb, and explain they can truncate the string to zero length:
Hello Friends%.0s
or even shorter:
Hello Friends%.s
The output is plain:
> Hello Friends
答案3
得分: 4
我同意Volker的答案,但你可以检查一下你的输入字符串:
package main
import (
"fmt"
"strings"
)
func main() {
tmp_str := "hello %s"
res := tmp_str
if strings.Count(tmp_str, "%s") == 1 {
res = fmt.Sprintf(tmp_str, "world")
}
fmt.Println(res)
}
英文:
I agree with Volker's answer, but you could check your input string:
package main
import (
"fmt"
"strings"
)
func main() {
tmp_str := "hello %s"
res := tmp_str
if strings.Count(tmp_str, "%s") == 1 {
res = fmt.Sprintf(tmp_str, "world")
}
fmt.Println(res)
}
答案4
得分: 0
我使用这个(可能可以扩展):
Sprintf("Hello"+"%[2]s", "World", "")
Sprintf("Hello %s"+"%[2]s", "World", "")
我帮你翻译了你提供的代码部分。
英文:
I use this one (which can probably be expanded on)
Sprintf("Hello"+"%[2]s", "World", "")
Sprintf("Hello %s"+"%[2]s", "World", "")
答案5
得分: -7
你不能这样做。
你必须找到一个不同的解决方案。
英文:
You cannot do this.
You have to find a different solution.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论