golang实现Python风格文本自动换行处理的插件库textwrap的使用
Golang实现Python风格文本自动换行处理的插件库textwrap的使用
这是一个为Go语言移植的Python "textwrap"模块。虽然功能上还有些差异…
限制
目前这个模块(至少现在)不会像英语习惯那样在空白处和连字符复合词后换行。因此,break_on_hyphens
和break_long_words
功能暂时还不支持。
同样,fix_sentence_endings
目前也不支持,这个功能在Python中本来就不太可靠(因为它需要两个空格和其他没人关心的条件)。
连字符支持的实现已在计划中,而fix_sentence_endings
则没有(但是!欢迎提交PR自由实现它)。
使用方法
使用方法与Python中非常相似:
import (
"fmt"
"github.com/isbm/textwrap"
)
...
text := "Your very long text here"
wrapper := textwrap.NewTextWrap() // 默认70个字符宽度
fmt.Println(wrapper.Fill(text)) // 返回字符串
// 获取每一行
for idx, line := range wrapper.Wrap(text) {
fmt.Println(idx, line)
}
去缩进功能也已实现,工作方式与Python完全相同:
multilineText := `
There is some multiline text
with different identation
everywhere. So it will be
aligned to the minimal.
`
// 这将从每行移除两个前导空格
fmt.Println(wrapper.Dedent(multilineText))
配置
你可以通过以下方式设置包装器对象的构造函数(给出的值是默认值,你可以根据需要更改它们):
wrapper := textwrap.NewTextWrap().
SetNewLine("\n").
SetWidth(70),
SetTabSpacesWidth(4).
SetDropWhitespace(true).
SetInitialIndent("").
SetReplaceWhitespace(true)
额外功能
虽然可以用其他方式实现,但这个模块还提供了仅去除前导空白(TrimLeft
)或仅去除尾部空白(TrimRight
)的字符串空白修剪功能,与strings.TrimSpace
修剪所有空白不同。
空白定义与Python的strings.whitespace
相同。
更多关于golang实现Python风格文本自动换行处理的插件库textwrap的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现Python风格文本自动换行处理的插件库textwrap的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 实现 Python 风格文本自动换行处理
在 Python 中,textwrap
模块提供了方便的文本自动换行功能。在 Go 中虽然没有完全相同的标准库,但我们可以通过组合标准库功能或使用第三方库来实现类似的功能。
使用标准库实现基础换行功能
Go 的 text/tabwriter
和 strings
包可以提供基本的换行功能:
package main
import (
"fmt"
"strings"
"text/tabwriter"
"bytes"
)
// WrapText 实现类似Python textwrap的功能
func WrapText(text string, width int) string {
// 使用tabwriter实现简单的换行
var buf bytes.Buffer
w := tabwriter.NewWriter(&buf, width, 1, 1, ' ', tabwriter.DiscardEmptyColumns)
fmt.Fprint(w, text)
w.Flush()
// 处理换行后的文本
wrapped := buf.String()
// 移除多余的空格
wrapped = strings.ReplaceAll(wrapped, "\t", " ")
wrapped = strings.ReplaceAll(wrapped, " \n", "\n")
return wrapped
}
func main() {
text := "This is a long text that needs to be wrapped to fit within a certain width. It should break at word boundaries and maintain proper spacing."
wrapped := WrapText(text, 40)
fmt.Println("Wrapped text (40 columns):")
fmt.Println(wrapped)
wrapped = WrapText(text, 60)
fmt.Println("\nWrapped text (60 columns):")
fmt.Println(wrapped)
}
使用第三方库实现更完整的功能
对于更完整的 Python textwrap
功能,可以使用第三方库如 github.com/mitchellh/go-wordwrap
:
package main
import (
"fmt"
"github.com/mitchellh/go-wordwrap"
)
func main() {
text := "This is a long text that needs to be wrapped to fit within a certain width. It should break at word boundaries and maintain proper spacing."
// 基本换行
wrapped := wordwrap.WrapString(text, 40)
fmt.Println("Basic wrapping (40 columns):")
fmt.Println(wrapped)
// 带缩进的换行
indented := wordwrap.WrapString(text, 36) // 40 - 4 spaces
indented = " " + strings.ReplaceAll(indented, "\n", "\n ")
fmt.Println("\nIndented wrapping (4 spaces, 40 columns total):")
fmt.Println(indented)
}
实现更接近 Python textwrap 的完整功能
如果需要更接近 Python textwrap
的功能,可以自己实现一个更完整的版本:
package textwrap
import (
"strings"
"unicode"
)
// Wrap 类似于Python的textwrap.wrap
func Wrap(text string, width int, opts ...Option) []string {
cfg := &config{width: width}
for _, opt := range opts {
opt(cfg)
}
// 处理初始缩进
lines := strings.Split(text, "\n")
var result []string
for _, line := range lines {
line = strings.TrimRightFunc(line, unicode.IsSpace)
if line == "" {
if !cfg.dropWhitespace {
result = append(result, "")
}
continue
}
// 处理缩进
indent := cfg.initialIndent
if len(result) > 0 {
indent = cfg.subsequentIndent
}
// 实际换行逻辑
words := strings.Fields(line)
var currentLine strings.Builder
currentLine.WriteString(indent)
currentLength := len(indent)
for _, word := range words {
if currentLength+len(word)+1 > cfg.width && currentLength > 0 {
result = append(result, currentLine.String())
currentLine.Reset()
currentLine.WriteString(cfg.subsequentIndent)
currentLength = len(cfg.subsequentIndent)
}
if currentLength > len(cfg.subsequentIndent) {
currentLine.WriteByte(' ')
currentLength++
}
currentLine.WriteString(word)
currentLength += len(word)
}
if currentLine.Len() > 0 {
result = append(result, currentLine.String())
}
}
return result
}
type config struct {
width int
initialIndent string
subsequentIndent string
dropWhitespace bool
}
type Option func(*config)
func Width(w int) Option {
return func(c *config) {
c.width = w
}
}
func InitialIndent(indent string) Option {
return func(c *config) {
c.initialIndent = indent
}
}
func SubsequentIndent(indent string) Option {
return func(c *config) {
c.subsequentIndent = indent
}
}
func DropWhitespace(drop bool) Option {
return func(c *config) {
c.dropWhitespace = drop
}
}
使用示例:
package main
import (
"fmt"
"./textwrap" // 假设上面的代码在textwrap包中
)
func main() {
text := "This is a long text that needs to be wrapped to fit within a certain width. It should break at word boundaries and maintain proper spacing."
// 基本换行
wrapped := textwrap.Wrap(text, 40)
fmt.Println("Basic wrapping (40 columns):")
for _, line := range wrapped {
fmt.Println(line)
}
// 带缩进的换行
wrapped = textwrap.Wrap(text, 40,
textwrap.InitialIndent(" "),
textwrap.SubsequentIndent(" "),
)
fmt.Println("\nIndented wrapping:")
for _, line := range wrapped {
fmt.Println(line)
}
}
总结
Go 中实现 Python 风格的文本换行有几种选择:
- 使用标准库的简单组合实现基本功能
- 使用第三方库如
go-wordwrap
获得更专业的处理 - 自己实现完整的
textwrap
功能
根据项目需求选择最适合的方案。对于大多数简单用例,标准库组合或 go-wordwrap
就足够了。如果需要完全匹配 Python 的 textwrap
行为,可能需要自己实现更完整的版本。