Skip to content

Commit ae5f33b

Browse files
authored
Merge pull request #11 from hectorcorrea/matchFields
Match fields
2 parents 59f1aa9 + 63dfed1 commit ae5f33b

File tree

9 files changed

+78
-39
lines changed

9 files changed

+78
-39
lines changed

README.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,46 @@ On the Mac or Linux the easiest way to install `marcli` is via Homebrew:
99

1010
```
1111
brew install marcli
12+
marcli -file yourfile.mrc
1213
```
1314

1415
Or by downloading the binary for your OS from the [releases tab](https://github.com/hectorcorrea/marcli/releases) and marking the downloaded file as an executable:
1516

1617
```
1718
curl -LO https://github.com/hectorcorrea/marcli/releases/latest/download/marcli
1819
chmod u+x marcli
19-
```
20-
21-
Once installed you can just run it via:
22-
23-
```
2420
./marcli -file yourfile.mrc
2521
```
2622

23+
Notice that if you install `marcli` via Homebrew the executable will be on your path and you can run it just by typing `marcli` from any folder, whereas if you install it via cURL you need to indicate the path `./marcli`.
2724

2825
## Sample of usage
2926

30-
Output MARC data to the console in a line delimited format:
27+
Output MARC data to the console in a line delimited format (`marcli` automatically detects whether the file provided is in MARC XML or MARC binary):
28+
3129
```
3230
./marcli -file data/test_1a.mrc
31+
./marcli -file data/test_10.xml
3332
```
3433

35-
If the file extension is `.xml` the file is expected to be a MARC XML file, otherwise MARC binary is assumed.
36-
3734
Extract MARC records on file that contain the string "wildlife"
3835
```
3936
./marcli -file data/test_10.mrc -match wildlife
4037
```
4138

42-
Extracts MARC records on file that contain the string "wildlife" but outputs only fields "LDR,001,040,245a,650" for each record.
39+
Extracts MARC records on file that contain the string "wildlife" but outputs only fields "LDR,001,040,245a,650" for each record, LDR means the leader of the MARC record. In the `-fields` parameter a letter (or letters) after the field tag indicates to output only those subfields. For example "907xz" means output subfield "x" and "z" in field "907".
4340

4441
```
4542
./marcli -file data/test_10.mrc -match wildlife -fields LDR,010,040,245a,650
4643
```
4744

48-
LDR means the leader of the MARC record.
45+
The `-matchFields` parameter can be used to limit the fields where the match will be made:
4946

50-
A letter (or letters) after the field tag indicates to output only those subfields. For example "907xz" means output subfield "x" and "z" in field "907".
47+
```
48+
./marcli -file=data/test_10.mrc -match=web -matchFields=530
49+
````
5150
52-
You can also use the `exclude` option to indicate fields to exclude from the output (notice that only full subfields are supported here, e.g. 970 is accepted but not 970a)
51+
You can also use the `exclude` option to indicate fields to exclude from the output (notice that only full fields are supported here, e.g. 970 is accepted but not 970a)
5352
5453
You can also filter based on the presence of certain fields in the MARC record (regardless of their value), for example the following will only output records that have a MARC 110 field:
5554

cmd/marcli/json.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func toJson(params ProcessFileParams) error {
4242
if i++; i < start {
4343
continue
4444
}
45-
if r.Contains(params.searchValue) && r.HasFields(params.hasFields) {
45+
if r.Contains(params.searchValue, params.searchFields) && r.HasFields(params.hasFields) {
4646
if out > 0 {
4747
fmt.Printf(",\r\n")
4848
} else {

cmd/marcli/main.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import (
99
"github.com/hectorcorrea/marcli/pkg/marc"
1010
)
1111

12-
var fileName, search, fields, exclude, format, hasFields string
12+
var fileName, search, searchFields, fields, exclude, format, hasFields string
1313
var start, count int
1414
var debug bool
1515

1616
func init() {
1717
flag.StringVar(&fileName, "file", "", "MARC file to process. Required.")
1818
flag.StringVar(&search, "match", "", "String that must be present in the content of the record, case insensitive.")
19+
flag.StringVar(&searchFields, "matchFields", "", "Comma delimited list of fields to search, used when match parameter is indicated, defaults to all fields.")
1920
flag.StringVar(&fields, "fields", "", "Comma delimited list of fields to output.")
2021
flag.StringVar(&exclude, "exclude", "", "Comma delimited list of fields to exclude from the output.")
2122
flag.StringVar(&format, "format", "mrk", "Output format. Accepted values: mrk, mrc, xml, json, or solr.")
@@ -33,14 +34,15 @@ func main() {
3334
}
3435

3536
params := ProcessFileParams{
36-
filename: fileName,
37-
searchValue: strings.ToLower(search),
38-
filters: marc.NewFieldFilters(fields),
39-
exclude: marc.NewFieldFilters(exclude),
40-
start: start,
41-
count: count,
42-
hasFields: marc.NewFieldFilters(hasFields),
43-
debug: debug,
37+
filename: fileName,
38+
searchValue: strings.ToLower(search),
39+
searchFields: searchFieldsFromString(searchFields),
40+
filters: marc.NewFieldFilters(fields),
41+
exclude: marc.NewFieldFilters(exclude),
42+
start: start,
43+
count: count,
44+
hasFields: marc.NewFieldFilters(hasFields),
45+
debug: debug,
4446
}
4547

4648
if len(params.filters.Fields) > 0 && len(params.exclude.Fields) > 0 {
@@ -73,12 +75,26 @@ func showSyntax() {
7375
fmt.Printf("\r\n")
7476
fmt.Printf(`
7577
NOTES:
76-
The match parameter is used to filter records based on the content of the
77-
values in the record. The hasFields parameter is used to filter records based
78-
on the presence of certain fields on the record (regardless of their value).
78+
The match parameter is used to filter records based on their content.
79+
By default marcli searches in all the fields for each record, you can use
80+
the matchFields parameter to limit the search to only certain fields (subfields
81+
are not supported in matchFields, i.e. 245 is OK, 245a is not)
82+
83+
The hasFields parameter is used to filter records based on the presence
84+
of certain fields on the record (regardless of their value).
7985
8086
You can only use the fields or exclude parameter, but not both.
8187
`)
8288
fmt.Printf("\r\n")
8389
fmt.Printf("\r\n")
8490
}
91+
92+
func searchFieldsFromString(searchFieldsString string) []string {
93+
values := []string{}
94+
for _, value := range strings.Split(searchFieldsString, ",") {
95+
if strings.TrimSpace(searchFieldsString) != "" {
96+
values = append(values, value)
97+
}
98+
}
99+
return values
100+
}

cmd/marcli/mrc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func toMrc(params ProcessFileParams) error {
3939
continue
4040
}
4141

42-
if r.Contains(params.searchValue) && r.HasFields(params.hasFields) {
42+
if r.Contains(params.searchValue, params.searchFields) && r.HasFields(params.hasFields) {
4343
fmt.Printf("%s", r.Raw())
4444
if out++; out == count {
4545
break

cmd/marcli/mrk.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func toMrk(params ProcessFileParams) error {
4444
continue
4545
}
4646

47-
if r.Contains(params.searchValue) && r.HasFields(params.hasFields) {
47+
if r.Contains(params.searchValue, params.searchFields) && r.HasFields(params.hasFields) {
4848
str := ""
4949
if params.filters.IncludeLeader() {
5050
str += fmt.Sprintf("%s\r\n", r.Leader)

cmd/marcli/processFileParams.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import (
55
)
66

77
type ProcessFileParams struct {
8-
filename string
9-
searchValue string
10-
filters marc.FieldFilters
11-
exclude marc.FieldFilters
12-
start int
13-
count int
14-
hasFields marc.FieldFilters
15-
debug bool
8+
filename string
9+
searchValue string
10+
searchFields []string
11+
filters marc.FieldFilters
12+
exclude marc.FieldFilters
13+
start int
14+
count int
15+
hasFields marc.FieldFilters
16+
debug bool
1617
}
1718

1819
func (p ProcessFileParams) HasFilters() bool {

cmd/marcli/solr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func toSolr(params ProcessFileParams) error {
9393
if i++; i < start {
9494
continue
9595
}
96-
if r.Contains(params.searchValue) && r.HasFields(params.hasFields) {
96+
if r.Contains(params.searchValue, params.searchFields) && r.HasFields(params.hasFields) {
9797
if out > 0 {
9898
fmt.Printf(",\r\n")
9999
} else {

cmd/marcli/xml.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func toXML(params ProcessFileParams) error {
7070
continue
7171
}
7272

73-
if r.Contains(params.searchValue) && r.HasFields(params.hasFields) {
73+
if r.Contains(params.searchValue, params.searchFields) && r.HasFields(params.hasFields) {
7474
str, err := recordToXML(r, params)
7575
if err != nil {
7676
if params.debug {

pkg/marc/record.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,25 @@ type Record struct {
1414
}
1515

1616
// Contains returns true if Record contains the value passed.
17-
func (r Record) Contains(searchValue string) bool {
17+
// If searchFieldList is an empty array it searches in all fields for the record
18+
// otherwise the search is limited to only the fields in the array.
19+
func (r Record) Contains(searchValue string, searchFieldsList []string) bool {
1820
if searchValue == "" {
1921
return true
2022
}
21-
for _, field := range r.Fields {
23+
24+
var searchFields []Field
25+
if len(searchFieldsList) == 0 {
26+
searchFields = r.Fields
27+
} else {
28+
for _, field := range r.Fields {
29+
if r.arrayContains(searchFieldsList, field.Tag) {
30+
searchFields = append(searchFields, field)
31+
}
32+
}
33+
}
34+
35+
for _, field := range searchFields {
2236
if field.Contains(searchValue) {
2337
return true
2438
}
@@ -175,3 +189,12 @@ func (r Record) GetValues(tag string, subfield string) []string {
175189
}
176190
return values
177191
}
192+
193+
func (r Record) arrayContains(array []string, value string) bool {
194+
for _, element := range array {
195+
if element == value {
196+
return true
197+
}
198+
}
199+
return false
200+
}

0 commit comments

Comments
 (0)