如何在 fmt.Sprintf 中忽略额外的字段

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

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)
}

演示1

演示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 1

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.

huangapple
  • 本文由 发表于 2016年1月28日 00:45:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/35043202.html
匿名

发表评论

匿名网友

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

确定