Пример #1
0
func SubmatchSplit(header []string, RS, LinePattern string, Stdin io.Reader) (ret interface{}, err error) {
	rs, err := cmpl(RS) //might as well add these to the cache
	if err != nil {
		return
	}

	lp, err := cmpl(LinePattern)
	if err != nil {
		return
	}

	//code loosely based on but entirely inspired by rsc's reply to
	//https://groups.google.com/forum/#!topic/golang-nuts/4LpRZDfNXIc
	if lp.NumSubexp() < 1 {
		return nil, errors.New("submatch splitting requires a regexp with submatches")
	}
	names := hdr2map(header, true)
	if len(names) == 0 {
		for i, name := range lp.SubexpNames() {
			if name != "" {
				names[name] = i
			}
		}
	}

	stdin, err := ioutil.ReadAll(Stdin)
	if err != nil {
		return
	}

	pairs := rs.FindAllIndex(stdin, -1)
	records := invert.Indicies(pairs, len(stdin))
	if len(names) > 0 {
		//if there are named submatches build the row as a map with just the named entries.
		//multiple names are by construction the value of the last name.
		out := make([]map[string]string, 0, len(records))
		for _, p := range records {
			if sms := lp.FindSubmatch(stdin[p[0]:p[1]]); sms != nil {
				row := make(map[string]string, len(names))
				for name, i := range names {
					if i < len(sms) {
						row[name] = string(sms[i])
					} else {
						row[name] = ""
					}
				}
				out = append(out, row)
			}

		}
		ret = out
	} else {
		out := make([]*record, 0, len(records))
		for _, p := range records {
			line := stdin[p[0]:p[1]]
			if sms := lp.FindSubmatch(line); sms != nil {
				row := make([]string, 0, len(sms)-1)
				for _, sm := range sms[1:] {
					row = append(row, string(sm))
				}
				out = append(out, &record{
					Fields: row,
					Line:   string(line),
				})
			}
		}
		ret = out
	}

	return
}
Пример #2
0
func Split(header []string, RS, FS string, Stdin io.Reader) (ret interface{}, err error) {
	rs, err := cmpl(RS)
	if err != nil {
		return
	}

	fs, err := cmpl(FS)
	if err != nil {
		return
	}

	stdin, err := ioutil.ReadAll(Stdin)
	if err != nil {
		return
	}

	names := hdr2map(header, false)

	pairs := rs.FindAllIndex(stdin, -1)
	records := invert.Indicies(pairs, len(stdin))
	if len(names) > 0 {
		out := make([]map[string]string, 0, len(records))
		for _, p := range records {
			s := stdin[p[0]:p[1]]

			is := fs.FindAllIndex(s, -1)
			is = invert.Indicies(is, len(s))

			row := make(map[string]string, len(names))
			for name, i := range names {
				if i < len(is) {
					ix := is[i]
					row[name] = string(s[ix[0]:ix[1]])
				} else {
					row[name] = ""
				}
			}
			out = append(out, row)
		}
		ret = out
	} else {
		out := make([]*record, 0, len(records))
		for _, p := range records {
			s := stdin[p[0]:p[1]]

			is := fs.FindAllIndex(s, -1)
			is = invert.Indicies(is, len(s))

			row := make([]string, 0, len(is))
			for _, ix := range is {
				row = append(row, string(s[ix[0]:ix[1]]))
			}

			out = append(out, &record{
				Fields: row,
				Line:   string(s),
			})
		}
		ret = out
	}

	return
}