使用regexp逐个值同时读取两个文件
将两个文本文件合并为一个的小帮助工具。 这些文件存储一个大的二维浮点值数组。以下是其中一些:使用regexp逐个值同时读取两个文件,regex,go,simultaneous,Regex,Go,Simultaneous,将两个文本文件合并为一个的小帮助工具。 这些文件存储一个大的二维浮点值数组。以下是其中一些: File 1 -0,1296169 -0,1286087 -0,1276232 ... -0,1288124 -0,1278683 -0,1269373 ... -0,1280221 -0,1271375 -0,12626 ... ... File 2 -0,1181779 -0,1200798 -0,1219472 ... -0,1198357 -0,1216468 -0,1234369 ...
File 1
-0,1296169 -0,1286087 -0,1276232 ...
-0,1288124 -0,1278683 -0,1269373 ...
-0,1280221 -0,1271375 -0,12626 ...
...
File 2
-0,1181779 -0,1200798 -0,1219472 ...
-0,1198357 -0,1216468 -0,1234369 ...
-0,1214746 -0,1232006 -0,1249159 ...
...
both may have hunderds of rows and columns ...
数值也可以采用科学形式(等1.234e-003)。
我的目标是逐值同时读取两个文件并写入输出,同时将delimeter从逗号固定到点,并在此过程中从科学形式转换到标准形式
这个版本的程序只合并了预处理的文件(delimeter更改为point,以标准形式表示的值和“每行一个值”移动的值),但如果文件的值超过百万,则进行这些准备是不真实的
以下是我目前的情况:
import (
"bufio"
"fmt"
"io"
"os"
"regexp"
)
func main() {
file_dB, err := os.Open("d:/dB.txt")
if err != nil {
fmt.Printf("error opening file: %v\n", err)
os.Exit(1)
}
file_dL, err := os.Open("d:/dL.txt")
if err != nil {
fmt.Printf("error opening file: %v\n", err)
os.Exit(1)
}
file_out, err := os.Create("d:/out.txt") // also rewrite existing !
if err != nil {
fmt.Printf("error opening file: %v\n", err)
os.Exit(1)
}
dB := bufio.NewReader(file_dB)
dL := bufio.NewReader(file_dL)
err = nil
i := 1
for {
line1, _, err := dB.ReadLine()
if len(line1) > 0 && line1[len(line1)-1] == '\n' {
line1 = line1[:len(line1)-1]
}
line2, _, err := dL.ReadLine()
if len(line2) > 0 && line2[len(line2)-1] == '\n' {
line2 = line2[:len(line2)-1]
}
if len(line1) == 0 || len(line2) == 0 || err == io.EOF {
fmt.Println("Total lines done: ", i)
break
} else if err != nil {
fmt.Printf("Error while reading files: %v\n", err)
os.Exit(1)
}
i++
str := string(line1) + ";" + string(line2) + "\n"
if _, err := file_out.WriteString(str); err != nil {
panic(err)
}
}
}
如何使用regexp使此程序逐值读取未显示的文件(第一个列表),并将其形成如下形式:
-0.129617;-0.118178
-0.128609;-0.120080
-0.127623;-0.121947
...
输入文件的格式始终相同:
-小数点分隔符是逗号
-值后一个空格(即使最后一行)
-换行符在行尾
以前使用的表达式,如([-?])([0-9]{1})([,]{1})([0-9]{1,12})({1})
和记事本++替换函数,将一行值拆分为每行一个值(与新的变量组合使用的表达式,如$1$2.$4\r\n\
),但如果出现“科学形式”值,则会造成混乱
那么,有没有办法一个值一个值地读取文件,而不必将行拆分成片/子字符串并对其进行处理呢?类似这样的内容。请注意假设每行的值数相同的限制。要小心,如果这个假设是错误的,它会出错:)
主程序包
进口(
“布菲奥”
“fmt”
“操作系统”
“strconv”
“字符串”
)
func main(){
文件\u dB,err:=os.Open(“dB.txt”)
如果错误!=零{
fmt.Printf(“打开文件时出错:%v\n”,错误)
返回
}
延迟文件\u dB.Close()
文件_dL,err:=os.Open(“dL.txt”)
如果错误!=零{
fmt.Printf(“打开文件时出错:%v\n”,错误)
返回
}
延迟文件\u dL.Close()
file_out,err:=os.Create(“out.txt”)//也重写现有的!
如果错误!=零{
fmt.Printf(“打开文件时出错:%v\n”,错误)
返回
}
延迟文件输出。关闭()
dB:=bufio.NewReader(文件\u dB)
dL:=bufio.NewReader(文件\u-dL)
立法会:=0
为了{
信用证++
第1行,错误:=dB.ReadLine()
vals1:=strings.Split(字符串(第1行),“”)
如果错误!=零{
格式打印LN(信用证,错误)
返回
}
第2行,错误:=dL.ReadLine()
vals2:=strings.Split(字符串(第2行),“”)
如果错误!=零{
格式打印LN(信用证,错误)
返回
}
//限制:假设第1行和第2行每行具有相同数量的值
对于i:=范围1{
dot1:=strings.Replace(vals1[i],“,”,“,”,1)
v1,err:=strconv.ParseFloat(dot1,64)
如果错误!=零{
格式打印LN(信用证,错误)
持续
}
dot2:=字符串.Replace(vals2[i],“,”,“,”,1)
v2,err:=strconv.ParseFloat(dot2,64)
如果错误!=零{
格式打印LN(信用证,错误)
持续
}
_,err=fmt.Fprintf(文件输出,“%v;%v\n”,v1,v2)
如果错误!=零{
格式打印LN(信用证,错误)
返回
}
}
}
}
例如
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"strconv"
"strings"
)
var comma, period = []byte{','}, []byte{'.'}
func readNext(r io.Reader) func() (float64, error) {
s := bufio.NewScanner(r)
var fields []string
return func() (float64, error) {
if len(fields) == 0 {
err := io.EOF
for s.Scan() {
line := bytes.Replace(s.Bytes(), comma, period, -1)
fields = strings.Fields(string(line))
if len(fields) > 0 {
err = nil
break
}
}
if err := s.Err(); err != nil {
return 0, err
}
if err == io.EOF {
return 0, err
}
}
n, err := strconv.ParseFloat(fields[0], 64)
fields = fields[1:]
if err != nil {
return 0, err
}
return n, nil
}
}
func main() {
in1Name := `in1.data`
in2Name := `in2.data`
outName := `out.data`
in1, err := os.Open(in1Name)
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
defer in1.Close()
in2, err := os.Open(in2Name)
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
defer in2.Close()
out, err := os.Create(outName)
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
defer out.Close()
outw := bufio.NewWriter(out)
defer outw.Flush()
next1 := readNext(in1)
next2 := readNext(in2)
for {
n1, err1 := next1()
n2, err2 := next2()
if err1 == io.EOF && err2 == io.EOF {
break
}
if err1 != nil || err2 != nil {
fmt.Fprint(os.Stderr, err1, err2)
return
}
_, err := fmt.Fprintf(outw, "%g;%g\n", n1, n2)
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
}
}
游乐场:
输出:
$ go run data.go
$ cat in1.data
-0,1296169 -0,1286087 -0,1276232
-0,1288124 -0,1278683 -0,1269373
-0,1280221 -0,1271375 -0,12626
$ cat in2.data
-0,1296169 -0,1286087 -0,1276232
-0,1288124 -0,1278683 -0,1269373
-0,1280221 -0,1271375 -0,12626
$ cat out.data
-0.1296169;-0.1296169
-0.1286087;-0.1286087
-0.1276232;-0.1276232
-0.1288124;-0.1288124
-0.1278683;-0.1278683
-0.1269373;-0.1269373
-0.1280221;-0.1280221
-0.1271375;-0.1271375
-0.12626;-0.12626
$
谢谢你的帮助,从其他民族的观点来看,我找到了自己的解决方案 此工具的作用是什么?通常它将两个文本文件合并为一个 我在哪里使用过它?为“国家特定坐标系工具”创建“通用ASCII”文本文件。输入文本文件是从GIS应用程序导出网格文件的ASCII格式(预期值为弧度)。稍后,当使用精确的GPS/GNSS接收机时,该文件可用于修复局部坐标偏移 以下是我“开发”的内容:
如果您有任何建议-请随时留言 我不明白你展示的输出是如何产生的?输出中每行上的两个值是什么?它们是否与第一个和第二个文件中的值相对应?这是怎么做到的?“将行拆分成片/子字符串并处理它们”可能会更快…:)您能为每个文件显示2个精确输入(5行)和预期的精确输出吗。确保两个值都使用科学记数法。文件第一行的前三个值是
-01296169-01286087-01276232…
,-01181779-01200798-01219472…
,应按照上一个列表所示进行修改,因此第一行由第一个文件的值组成,第二行由第二个文件的值组成(或第一行-来自这些文件的第一个值,第二行-第二个值…)。因此file1line1val1val2val3…
和file2line1val1val2val3…
出来了。txt:line1像val1;val1
,line2val2;val2
等等。来自@peterSO的版本更全面、更整洁。
package main
import (
"bufio"
"fmt"
"os"
"regexp"
"strconv"
"strings"
)
func main() {
file_dB, err := os.Open("d:/dB.txt")
if err != nil {
fmt.Printf("error opening file: %v\n", err)
os.Exit(1)
}
defer file_dB.Close()
file_dL, err := os.Open("d:/dL.txt")
if err != nil {
fmt.Printf("error opening file: %v\n", err)
os.Exit(1)
}
defer file_dL.Close()
file_out, err := os.Create("d:/out.txt") // also rewrite existing !
if err != nil {
fmt.Printf("error opening file: %v\n", err)
os.Exit(1)
}
defer file_out.Close()
dB := bufio.NewReader(file_dB)
dL := bufio.NewReader(file_dL)
err = nil
xcorn_float := 0.0
ycorn_float := 0.0
cellsize_float := 0.0
ncols := regexp.MustCompile("[0-9]+")
nrows := regexp.MustCompile("[0-9]+")
xcorn := regexp.MustCompile("[0-9]*,[0-9]*")
ycorn := regexp.MustCompile("[0-9]*,[0-9]*")
cellsize := regexp.MustCompile("[0-9]*,[0-9]*")
nodataval := regexp.MustCompile("-?d+")
tmp := 0.0
// n cols --------------------
ncols_dB, err := dB.ReadString('\n')
if err != nil {
panic(err)
}
ncols_dL, err := dL.ReadString('\n')
if err != nil {
panic(err)
}
if ncols.FindString(ncols_dB) != ncols.FindString(ncols_dL) {
panic(err)
}
ncols_dB = ncols.FindString(ncols_dB)
// n rows --------------------
nrows_dB, err := dB.ReadString('\n')
if err != nil {
panic(err)
}
nrows_dL, err := dL.ReadString('\n')
if err != nil {
panic(err)
}
if nrows.FindString(nrows_dB) != nrows.FindString(nrows_dL) {
panic(err)
}
nrows_dB = nrows.FindString(nrows_dB)
// X --------------------
xcorn_dB, err := dB.ReadString('\n')
if err != nil {
panic(err)
}
xcorn_dL, err := dL.ReadString('\n')
if err != nil {
panic(err)
}
if xcorn.FindString(xcorn_dB) != xcorn.FindString(xcorn_dL) {
panic(err)
}
xcorn_float, err = strconv.ParseFloat(strings.Replace(cellsize.FindString(xcorn_dB), ",", ".", 1), 8)
xcorn_float *= 3600.0
// Y --------------------
ycorn_dB, err := dB.ReadString('\n')
if err != nil {
panic(err)
}
ycorn_dL, err := dL.ReadString('\n')
if err != nil {
panic(err)
}
if ycorn.FindString(ycorn_dB) != ycorn.FindString(ycorn_dL) {
panic(err)
}
ycorn_float, err = strconv.ParseFloat(strings.Replace(cellsize.FindString(ycorn_dB), ",", ".", 1), 8)
ycorn_float *= 3600.0
// cell size --------------------
cellsize_dB, err := dB.ReadString('\n')
if err != nil {
panic(err)
}
cellsize_dL, err := dL.ReadString('\n')
if err != nil {
panic(err)
}
if cellsize.FindString(cellsize_dB) != cellsize.FindString(cellsize_dL) {
panic(err)
}
cellsize_float, err = strconv.ParseFloat(strings.Replace(cellsize.FindString(cellsize_dB), ",", ".", 1), 8)
cellsize_float *= 3600.0
// nodata value --------------------
nodataval_dB, err := dB.ReadString('\n')
if err != nil {
panic(err)
}
nodataval_dL, err := dL.ReadString('\n')
if err != nil {
panic(err)
}
if nodataval.FindString(nodataval_dB) != nodataval.FindString(nodataval_dL) {
panic(err)
}
nodataval_dB = nodataval.FindString(nodataval_dB)
fmt.Print(nodataval_dB)
//making header
if _, err := file_out.WriteString("name\n3;0;2\n1;2;" + nrows_dB + ";" + ncols_dB + "\n" + strconv.FormatFloat(xcorn_float, 'f', -1, 32) + ";" + strconv.FormatFloat(ycorn_float, 'f', -1, 32) + ";" + strconv.FormatFloat(cellsize_float, 'f', -1, 32) + ";" + strconv.FormatFloat(cellsize_float, 'f', -1, 32) + "\n1\n"); err != nil {
panic(err)
}
// valuses --------------------
for {
line1, err := dB.ReadString(' ')
if err != nil {
break
}
if tmp, err = strconv.ParseFloat(strings.TrimSpace(strings.Replace(line1, ",", ".", 1)), 64); err == nil {
line1 = strconv.FormatFloat(tmp, 'f', 8, 64)
}
line2, err := dL.ReadString(' ')
if err != nil {
break
}
if tmp, err = strconv.ParseFloat(strings.TrimSpace(strings.Replace(line2, ",", ".", 1)), 64); err == nil {
line2 = strconv.FormatFloat(tmp, 'f', 8, 64)
}
if err != nil {
panic(err)
}
str := string(line1) + ";" + string(line2) + "\n"
if _, err := file_out.WriteString(str); err != nil {
panic(err)
}
}
}