一,单词替换
1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "log" 9 "os" 10 "path/filepath" 11 "regexp" 12 "strings" 13 ) 14 15 var britishAmerican = "british-american.txt" 16 17 func init() { 18 dir, _ := filepath.Split(os.Args[0]) 19 britishAmerican = filepath.Join(dir, britishAmerican) 20 //fmt.Println("dir %s,file %s",dir,britishAmerican) 21 } 22 23 func main() { 24 inFilename, outFilename, err := filenamesFromCommandLine() 25 if err != nil { 26 fmt.Println(err) 27 os.Exit(1) 28 } 29 inFile, outFile := os.Stdin, os.Stdout 30 if inFilename != "" { 31 if inFile, err = os.Open(inFilename); err != nil { 32 log.Fatal(err) 33 } 34 defer inFile.Close() 35 } 36 if outFilename != "" { 37 if outFile, err = os.Create(outFilename); err != nil { 38 log.Fatal(err) 39 } 40 defer outFile.Close() 41 } 42 43 if err = americanise(inFile, outFile); err != nil { 44 log.Fatal(err) 45 } 46 } 47 48 func filenamesFromCommandLine() (inFilename, outFilename string, err error) { 49 if len(os.Args) > 1 && (os.Args[1] == "-h" || os.Args[1] == "--help") { 50 err = fmt.Errorf("usage :%s [<] infile.txt [>] outfile.txt", 51 filepath.Base(os.Args[0])) 52 return "", "", err 53 } 54 if len(os.Args) > 1 { 55 inFilename = os.Args[1] 56 if len(os.Args) > 2 { 57 outFilename = os.Args[2] 58 } 59 } 60 if inFilename != "" && inFilename == outFilename { 61 log.Fatal("won't overwrite the infile") 62 } 63 return inFilename, outFilename, nil 64 } 65 66 func americanise(inFile io.Reader, outFile io.Writer) (err error) { 67 reader := bufio.NewReader(inFile) 68 writer := bufio.NewWriter(outFile) 69 defer func() { 70 if err == nil { 71 err = writer.Flush() 72 } 73 }() 74 75 var replacer func(string) string 76 if replacer, err = makeReplacerFunction(britishAmerican); err != nil { 77 return err 78 } 79 wordRx := regexp.MustCompile("[A-Za-z]+") 80 eof := false 81 for !eof { 82 var line string 83 line, err = reader.ReadString(' ') 84 if err == io.EOF { 85 err = nil 86 eof = true 87 } else if err != nil { 88 return err 89 } 90 line = wordRx.ReplaceAllStringFunc(line, replacer) 91 if _, err = writer.WriteString(line); err != nil { 92 93 return err 94 } 95 } 96 return nil 97 } 98 99 func makeReplacerFunction(file string) (func(string) string, error) { 100 rawBytes, err := ioutil.ReadFile(file) 101 if err != nil { 102 return nil, err 103 } 104 text := string(rawBytes) 105 usForBritish := make(map[string]string) 106 lines := strings.Split(text, " ") 107 for _, line := range lines { 108 fields := strings.Fields(line) 109 if len(fields) == 2 { 110 usForBritish[fields[0]] = fields[1] 111 } 112 } 113 114 return func(word string) string { 115 if usWord, found := usForBritish[word]; found { 116 return usWord 117 } 118 return word 119 }, nil 120 }
这次的格式终于没错
这个功能里面,我觉得有几个要点,一个是闭包,一个是正则的替换,还有个defer做后事~
简单理解一下闭包,在构造一个函数的时候,同时让这个函数自带了一些数据等其他内容,比如这里定义这个replacer函数的时候,首先定义replacer的私有数据map,然后返回了使用这个map的函数。这样在调用replacer的时候,就可以使用这个map点数据。(好像说的有点混乱。。)
正则和defer就没啥好说的了。。