Skip to content

Commit

Permalink
Merge pull request #10 from onozaty/v1.7.0
Browse files Browse the repository at this point in the history
Develp v1.7.0
  • Loading branch information
onozaty authored Jul 7, 2021
2 parents c8d01fd + 53bc0e1 commit 2e9f1b1
Show file tree
Hide file tree
Showing 12 changed files with 1,516 additions and 20 deletions.
136 changes: 126 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
`csvt` consists of multiple subcommands.

* [choose](#choose) Choose columns.
* [exclude](#exclude) Exclude rows by included in another CSV file.
* [count](#count) Count the number of records.
* [filter](#filter) Filter rows.
* [filter](#filter) Filter rows by condition.
* [header](#header) Show header.
* [include](#include) Filter rows by included in another CSV file.
* [join](#join) Join CSV files.
* [remove](#remove) Remove columns.
* [rename](#rename) Rename columns.
Expand Down Expand Up @@ -87,6 +89,63 @@ Smith,30
Jun,22
```

## exclude

Create a new CSV file by exclude on the rows included in another CSV file.

### Usage

```
csvt exclude -i INPUT -c COLUMN -a ANOTHER [--column-another COLUMN2] -o OUTPUT
```

```
Usage:
csvt exclude [flags]
Flags:
-i, --input string Input CSV file path.
-c, --column string Name of the column to use for exclude.
-a, --another string Another CSV file path. Exclude by included in this CSV file.
--column-another string (optional) Name of the column to use for exclude in the another CSV file. Specify if different from the input CSV file.
-o, --output string Output CSV file path.
-h, --help help for exclude
```

### Example

The contents of `input.csv`.

```
col1,col2
1,A
2,B
3,C
4,D
```

The contents of `another.csv`.

```
col1,col3
2,2
3,2
```

Exclude by "col1" values in `another.csv`.

```
$ csvt exclude -i input.csv -c col1 -a another.csv -o output.csv
```

The contents of the created `output.csv`.

```
col1,col2
1,A
4,D
```

## count

Count the number of records in CSV file.
Expand Down Expand Up @@ -286,6 +345,63 @@ Age
CompanyID
```

## include

Create a new CSV file by filtering on the rows included in another CSV file.

### Usage

```
csvt include -i INPUT -c COLUMN -a ANOTHER [--column-another COLUMN2] -o OUTPUT
```

```
Usage:
csvt include [flags]
Flags:
-i, --input string Input CSV file path.
-c, --column string Name of the column to use for filtering.
-a, --another string Another CSV file path. Filter by included in this CSV file.
--column-another string (optional) Name of the column to use for filtering in the another CSV file. Specify if different from the input CSV file.
-o, --output string Output CSV file path.
-h, --help help for include
```

### Example

The contents of `input.csv`.

```
col1,col2
1,A
2,B
3,C
4,D
```

The contents of `another.csv`.

```
col1,col3
2,2
3,2
```

Filter by "col1" values in `another.csv`.

```
$ csvt include -i input.csv -c col1 -a another.csv -o output.csv
```

The contents of the created `output.csv`.

```
col1,col2
2,B
3,C
```

## join

Join CSV files.
Expand All @@ -304,14 +420,14 @@ Usage:
csvt join [flags]
Flags:
-1, --first string First CSV file path.
-2, --second string Second CSV file path.
-c, --column string Name of the column to use for joining.
--column2 string (optional) Name of the column to use for joining in the second CSV file. Specify if different from the first CSV file.
-o, --output string Output CSV file path.
--usingfile (optional) Use temporary files for joining. Use this when joining large files that will not fit in memory.
--norecord (optional) No error even if there is no record corresponding to sencod CSV.
-h, --help help for join
-1, --first string First CSV file path.
-2, --second string Second CSV file path.
-c, --column string Name of the column to use for joining.
--column-second string (optional) Name of the column to use for joining in the second CSV file. Specify if different from the first CSV file.
-o, --output string Output CSV file path.
--usingfile (optional) Use temporary files for joining. Use this when joining large files that will not fit in memory.
--norecord (optional) No error even if there is no record corresponding to sencod CSV.
-h, --help help for join
```

### Example
Expand Down Expand Up @@ -366,7 +482,7 @@ If you don't want to raise an error even if there is no value, specify `--noreco
$ csvt join -1 input1.csv -2 input2.csv -c CompanyID -o output.csv --norecord
```

If the column name in the second CSV file is different from that in the first CSV file, specify it with `--column2`.
If the column name in the second CSV file is different from that in the first CSV file, specify it with `--column-second`.

```
$ csvt join -1 input1.csv -2 input2.csv -c CompanyID --column2 ID -o output.csv
Expand Down
129 changes: 129 additions & 0 deletions cmd/exclude.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package cmd

import (
"fmt"
"io"

"github.com/onozaty/csvt/csv"
"github.com/onozaty/csvt/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

func newExcludeCmd() *cobra.Command {

excludeCmd := &cobra.Command{
Use: "exclude",
Short: "Exclude rows by included in another CSV file",
RunE: func(cmd *cobra.Command, args []string) error {

format, err := getFlagBaseCsvFormat(cmd.Flags())
if err != nil {
return err
}

inputPath, _ := cmd.Flags().GetString("input")
targetColumnName, _ := cmd.Flags().GetString("column")
anotherPath, _ := cmd.Flags().GetString("another")
anotherColumnName, _ := cmd.Flags().GetString("column-another")
outputPath, _ := cmd.Flags().GetString("output")

// 引数の解析に成功した時点で、エラーが起きてもUsageは表示しない
cmd.SilenceUsage = true

return runExclude(
format,
inputPath,
targetColumnName,
anotherPath,
outputPath,
ExcludeOptions{
anotherColumnName: anotherColumnName,
})
},
}

excludeCmd.Flags().StringP("input", "i", "", "Input CSV file path.")
excludeCmd.MarkFlagRequired("input")
excludeCmd.Flags().StringP("column", "c", "", "Name of the column to use for exclude.")
excludeCmd.MarkFlagRequired("column")
excludeCmd.Flags().StringP("another", "a", "", "Another CSV file path. Exclude by included in this CSV file.")
excludeCmd.MarkFlagRequired("another")
excludeCmd.Flags().StringP("column-another", "", "", "(optional) Name of the column to use for exclude in the another CSV file. Specify if different from the input CSV file.")
excludeCmd.Flags().StringP("output", "o", "", "Output CSV file path.")
excludeCmd.MarkFlagRequired("output")

return excludeCmd
}

type ExcludeOptions struct {
anotherColumnName string
}

func runExclude(format csv.Format, inputPath string, targetColumnName string, anotherPath string, outputPath string, options ExcludeOptions) error {

reader, writer, close, err := setupInputOutput(inputPath, outputPath, format)
if err != nil {
return err
}
defer close()

anotherReader, anotherClose, err := setupInput(anotherPath, format)
if err != nil {
return err
}
defer anotherClose()

err = exclude(reader, targetColumnName, anotherReader, writer, options)
if err != nil {
return err
}

return writer.Flush()
}

func exclude(reader csv.CsvReader, targetColumnName string, anotherReader csv.CsvReader, writer csv.CsvWriter, options ExcludeOptions) error {

inputTargetColumnName := targetColumnName
anotherTargetColumnName := targetColumnName
if options.anotherColumnName != "" {
anotherTargetColumnName = options.anotherColumnName
}

inputColumnNames, err := reader.Read()
if err != nil {
return errors.Wrap(err, "failed to read the input CSV file")
}
inputTargetColumnIndex := util.IndexOf(inputColumnNames, inputTargetColumnName)
if inputTargetColumnIndex == -1 {
return fmt.Errorf("missing %s in the input CSV file", inputTargetColumnName)
}

anotherItemSet, err := csv.LoadItemSet(anotherReader, anotherTargetColumnName)
if err != nil {
return errors.Wrap(err, "failed to read the another CSV file")
}

writer.Write(inputColumnNames)

for {
row, err := reader.Read()
if err == io.EOF {
break
}
if err != nil {
return errors.Wrap(err, "failed to read the input CSV file")
}

// 比較対象のCSV内に存在ない場合は出力
if !anotherItemSet.Contains(row[inputTargetColumnIndex]) {

err = writer.Write(row)
if err != nil {
return err
}
}
}

return nil
}
Loading

0 comments on commit 2e9f1b1

Please sign in to comment.