go - Golang 中的文件清理
问题描述
我有一个看起来已损坏的 csv 文件,所以我想做一些清理工作。
将文件导入 MS Access 后,我得到了以下内容,这不是必需的:
我想将其作为txt
文件处理以进行清理,然后将其作为 csv 读取。
在文件中,我有一些字段,""
有些没有,并注意到其中""
包含一个,
,示例:
一些数字显示为:"2,15.0
而一些数字显示为22.3
没有""
一些文本显示为:Manager, Supply Chain
而一些文本显示为Supervisor
没有""
我解决这个问题的方法是:
,
如果介于两者之间,则从文件中删除""
""
从文件中删除
可以说我在文件中的行是:
John, supervisor, 20.22
Mark, "Manager, SC", "3,200.0"
Joseph, "Technician, Electrical", 15.2
"Selphia, Henry", "Manager, Lab", "4,250.0"
那么清理后的文件应该是:
John, supervisor, 20.22
Mark, Manager SC, 3200.0
Joseph, Technician Electrical, 15.2
Selphia Henry, Manager Lab, 4250.0
有什么想法,支持吗?
解决方案
感谢提供意见,set "text qualifier" to be double quote in that gui
问题已解决
要进行适当的清理,我们不应该在清理时损坏数据!"Manager, SC"
应该变成Manager, SC
.
逐步执行转换,检查每一步后的结果。
John, supervisor, 20.22
Mark, "Manager, SC", "3,200.0"
Joseph, "Technician, Electrical", 15.2
"Selphia, Henry", "Manager, Lab", "4,250.0"
.csv
像文件一样读取.txt
文件。('"')
对于每一行,用tabs替换不在引号内的逗号("\t" or 0x09)
。.csv
转换后用.tsv
文件扩展名写入输入文件。检查输出.tsv
文件。为了可见性,我在示例中显示了制表("\t" or 0x09)
符\t
。
John\t supervisor\t 20.22
Mark\t "Manager, SC"\t "3,200.0"
Joseph\t "Technician, Electrical"\t 15.2
"Selphia, Henry"\t "Manager, Lab"\t "4,250.0"
阅读.tsv
文件。对于每个字段,修剪前导和尾随空格。如果字段的第一个和最后一个字符是引号,则('"')
修剪它们。写.tsv
文件。检查输出.tsv
文件。
John\tsupervisor\t20.22
Mark\tManager, SC\t3,200.0
Joseph\tTechnician, Electrical\t15.2
Selphia, Henry\tManager, Lab\t4,250.0
阅读.tsv
文件。对于每个字段,如果删除逗号并strconv.ParseFloat
返回 err == nil 则删除逗号。写.tsv
文件。检查输出.tsv
文件。
John\tsupervisor\t20.22
Mark\tManager, SC\t3200.0
Joseph\tTechnician, Electrical\t15.2
Selphia, Henry\tManager, Lab\t4250.0
下面的代码可以进行所需的修剪:
package main
import (
"fmt"
"regexp"
"strings"
)
// https://yourbasic.org/golang/regexp-cheat-sheet/
func main() {
str1 := `"Selphia, Henry", "Manager, Lab", "4,250.0"` // {}
re := regexp.MustCompile(`"\s*|,\s*"`)
tsv := re.ReplaceAllString(str1, "\t")
s := strings.TrimSpace(tsv) // to remove the leading `\t` if generated
fmt.Println(s)
}
正则表达式可以在这里检查
对于.tsv
文件,使用包编码/csv:
rdr := csv.NewReader(file)
rdr.Comma = '\t'
更新
未引用字段中的前导空格很重要。使用“,”作为字段分隔符而不是“,”是错误的。例如,
John, supervisor, 20.22
在数字字段 (3,200.0) 中使用逗号需要引号来转义逗号。例如,
Mark, "Manager, SC", "3,200.0"
如果我们解决了最后两个问题,那么 csv 文件将是有效且可用的。例如,
John, supervisor, 20.22
Mark, "Manager, SC", "3,200.0"
Joseph, "Technician, Electrical", 15.2
"Selphia, Henry", "Manager, Lab", "4,250.0"
变成
John,supervisor,20.22
Mark,"Manager, SC",3200
Joseph,"Technician, Electrical",15.2
"Selphia, Henry","Manager, Lab",4250
使用 Go 包编码/csv,有一个简单的修复:
func cleanCSV(in io.Reader, out io.Writer) error {
r := csv.NewReader(in)
r.TrimLeadingSpace = true
w := csv.NewWriter(out)
for {
rec, err := r.Read()
if err != nil {
if err == io.EOF {
break
}
return err
}
for i, fld := range rec {
if strings.IndexByte(fld, ',') >= 0 {
fld = strings.Replace(fld, ",", "", -1)
if _, err := strconv.ParseFloat(fld, 64); err == nil {
rec[i] = fld
}
}
}
err = w.Write(rec)
if err != nil {
return err
}
}
w.Flush()
if err := w.Error(); err != nil {
return err
}
return nil
}
完整的程序(cleancsv.go):https: //play.golang.org/p/tEc6eXCuBWD
$ go build cleancsv.go
$ ./cleancsv -i=clean.in.csv -o=clean.out.csv
cleaned: in: clean.in.csv out: clean.out.csv
$ cat clean.in.csv
John, supervisor, 20.22
Mark, "Manager, SC", "3,200.0"
Joseph, "Technician, Electrical", 15.2
"Selphia, Henry", "Manager, Lab", "4,250.0"
$ cat clean.out.csv
John,supervisor,20.22
Mark,"Manager, SC",3200.0
Joseph,"Technician, Electrical",15.2
"Selphia, Henry","Manager, Lab",4250.0
为避免在字段中使用引号转义逗号,程序 (cleanantsv.go) 输出一个tsv
文件: https: //play.golang.org/p/6fOTX4_FqUM
package main
import (
"bufio"
"encoding/csv"
"flag"
"fmt"
"io"
"os"
"strconv"
"strings"
)
func cleanCSV(in io.Reader, out io.Writer) error {
r := csv.NewReader(in)
r.TrimLeadingSpace = true
w := bufio.NewWriter(out)
for {
rec, err := r.Read()
if err != nil {
if err == io.EOF {
break
}
return err
}
for i, fld := range rec {
if strings.IndexByte(fld, ',') >= 0 {
fld = strings.Replace(fld, ",", "", -1)
if _, err := strconv.ParseFloat(fld, 64); err == nil {
rec[i] = fld
}
}
}
_, err = w.WriteString(strings.Join(rec, "\t"))
if err != nil {
return err
}
_, err = w.WriteString("\n")
if err != nil {
return err
}
}
err := w.Flush()
if err != nil {
return err
}
return nil
}
func cleanFile(inFile, outFile string) error {
in, err := os.Open(inFile)
if err != nil {
return err
}
defer in.Close()
inName := in.Name()
out, err := os.Create(outFile)
if err != nil {
return err
}
defer out.Close()
outName := out.Name()
err = cleanCSV(in, out)
if err != nil {
return err
}
err = out.Close()
if err != nil {
return err
}
fmt.Println("cleaned:", "in:", inName, "out:", outName)
return nil
}
var (
inFile = flag.String("i", "", "input csv file")
outFile = flag.String("o", "", "output tsv file")
)
func main() {
flag.Parse()
if flag.NFlag() != 2 || *inFile == "" || *outFile == "" {
flag.Usage()
os.Exit(1)
}
err := cleanFile(*inFile, *outFile)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Remove(*outFile)
os.Exit(1)
}
}
推荐阅读
- asp.net-core-mvc - 出现错误“'java.util.Locale' 的类型初始化程序引发了异常。” 关于迎风的 Report.Init() 方法
- string - 在 XSLT 中选择部分字符串
- html - 如何对从火力基地检索到的对象列表进行排序?
- php - 是否可以在 php 文档上输出某些内容,并且仅当它的 URL 在 MySQL 数据库上的值为 true 时才使其消失?
- cardano - 为什么我们需要 Ouroboros BFT 作为从 Ouroboros Classic 到 Ouroboros Genesis 的迁移阶段?
- powershell - 选择下一行字符串以及与我的搜索匹配的字符串
- node.js - 嵌套包含续集
- java - 如何将类数组实例化为类的实例?
- python-3.x - 浮点数未转换为整数熊猫
- mysql - 节点js中的数据没有变化