04.4.2 简单的正则表达式示例

本节你将学习从一行文本中选择特定列的技巧。为了让这事儿更有趣,我还会教你如何逐行地读取文本,文本I/O是第8章的内容,你可以参考一下。

本节代码示例selectColumn.go将会分为4部分阐述,需要至少两个命令行参数进行操作;第一个是你想选择的第几列,第二个是你要处理的文本所在路径。当然,你可以处理多个文件,selectColumn.go将会帮你一个一个处理。

第一部分代码:

package main

import (
   "bufio"
   "fmt"
   "io"
   "os"
   "strconv"
   "strings"
)

func main() {
   arguments := os.Args
   if len(arguments) < 2 {
      fmt.Printf("usage: use selectColumn column [file1] [file2] [...]\n")
      os.Exit(1)
   }

   temp , err := strconv.Atoi(arguments[i])
   if err != nil  {
      fmt.Printf("column value is not an integer", temp)
      return
   }

   column := temp
   if column < 0 {
      fmt.Println("Invalid column value")
      os.Exit(1)
   }

首先判断输入的参数数量是否满足要求(len(arguments) < 2),然后需要判断输入的column值是否是合法的,即>0

第二部分代码:

for _, fileName := range arguments[2:]{
   fmt.Println("\t\t",fileName)
   f, err := os.Open(fileName)
   if err != nil {
      fmt.Printf("error opening file %s\n",err)
      continue
   }
   f.Close()

这部分代码判断所给的文件是否存在并且可读,os.Open()用来读取文本文件的。记住,UNIX系统的文件有些你是没有读权限的。

第三部分代码:

r := bufio.NewReader(f)
for {
   line, err := r.ReadString('\n')
   if err == io.EOF {
      break
   } else if err != nil{
      fmt.Printf("error reading file %s\n",err)
   }

你将在第8章中学习到bufio.ReadString()函数的机制是读取到参数中的字符就停止,所以bufio.ReadString('\n')的意思就是逐行读取文本文件,因为\n在UNIX系统中是换行符。bufio.ReadString()函数返回的是字节切片。

最后一部分代码是:

data := strings.Fields(line)
         if len(data) > column {
            fmt.Println(data[column-1])
         }
      }

   }

}

这个程序背后的逻辑是很简单的:逐行读取文本并选择你想要的列。然而,由于你不能确定当前行是否拥有你想要的列,所以你会在输出之前检查一下。其实这是一个非常简单的模式匹配,因为空格天然地充当了每一行中的分隔符。

如果你想要探究更多切分一行文本的技巧,可以查看strings.Fields()的源码,你就会发现该函数基于空白分隔符将一行文本分割成一个字符串切片,空白分隔符是由unicode.IsSpace()定义的。

执行selectColumn.go的输出如下:

$ go run selectColumn.go 15 /tmp/swtag.log /tmp/adobegc.log

AdobeDjkdgj

Successfully

Initializiing

Stream

*AdobeGC

Last updated