xlsxgrep 0.0.32__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xlsxgrep-0.0.32/LICENSE +21 -0
- xlsxgrep-0.0.32/MANIFEST.in +3 -0
- xlsxgrep-0.0.32/PKG-INFO +99 -0
- xlsxgrep-0.0.32/README.md +59 -0
- xlsxgrep-0.0.32/pyproject.toml +4 -0
- xlsxgrep-0.0.32/setup.cfg +53 -0
- xlsxgrep-0.0.32/setup.py +5 -0
- xlsxgrep-0.0.32/xlsxgrep/__init__.py +1 -0
- xlsxgrep-0.0.32/xlsxgrep/xlsxgrep.py +504 -0
- xlsxgrep-0.0.32/xlsxgrep.egg-info/PKG-INFO +99 -0
- xlsxgrep-0.0.32/xlsxgrep.egg-info/SOURCES.txt +14 -0
- xlsxgrep-0.0.32/xlsxgrep.egg-info/dependency_links.txt +1 -0
- xlsxgrep-0.0.32/xlsxgrep.egg-info/entry_points.txt +2 -0
- xlsxgrep-0.0.32/xlsxgrep.egg-info/requires.txt +4 -0
- xlsxgrep-0.0.32/xlsxgrep.egg-info/top_level.txt +1 -0
xlsxgrep-0.0.32/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Ivan Cvitic, zazuum.org
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
xlsxgrep-0.0.32/PKG-INFO
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xlsxgrep
|
|
3
|
+
Version: 0.0.32
|
|
4
|
+
Summary: CLI tool to search text in XLSX, XLS, XLSM, CSV, TSV and ODS files. It works similarly to Unix\GNU Linux grep.
|
|
5
|
+
Home-page: https://github.com/zazuum/xlsxgrep
|
|
6
|
+
Author: Ivan Cvitic
|
|
7
|
+
Author-email: cviticivan@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Education
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering
|
|
27
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
28
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
29
|
+
Classifier: Topic :: Office/Business
|
|
30
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
31
|
+
Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
|
|
32
|
+
Classifier: Topic :: Utilities
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: pyexcel
|
|
36
|
+
Requires-Dist: pyexcel-xls
|
|
37
|
+
Requires-Dist: pyexcel-xlsx
|
|
38
|
+
Requires-Dist: pyexcel-odsr
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
## Owerview
|
|
42
|
+
|
|
43
|
+
*xlsxgrep* is a CLI tool to search text in XLSX, XLS, XLSM, CSV, TSV and ODS files. It works similarly to Unix/GNU Linux *grep*.
|
|
44
|
+
|
|
45
|
+
## Features
|
|
46
|
+
|
|
47
|
+
- Grep compatible: xlsxgrep tries to be compatible with Unix/Linux grep, where it makes sense.
|
|
48
|
+
Some of grep options are supported (such as `-r`, `-i` or `-c`).
|
|
49
|
+
|
|
50
|
+
- Search many XLSX, XLS, XLSM, CSV, TSV and ODS files at once, even recursively in directories.
|
|
51
|
+
|
|
52
|
+
- Regular expressions: Python regex.
|
|
53
|
+
|
|
54
|
+
- Supported file types: csv, ods, tsv, xls, xlsx, xlsm.
|
|
55
|
+
|
|
56
|
+
- Works on all major platforms: Windows, macOS, BSD and Linux,
|
|
57
|
+
|
|
58
|
+
## Usage:
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
usage: xlsxgrep [-h] [-V] [-P] [-F] [-i] [-w] [-c] [-r] [-H] [-N] [-l] [-L] [-S SEPARATOR]
|
|
62
|
+
[-Z] [-d] PATTERN FILE [FILE ...]
|
|
63
|
+
|
|
64
|
+
positional arguments:
|
|
65
|
+
PATTERN use PATTERN as the pattern to search for.
|
|
66
|
+
FILE file or folder location.
|
|
67
|
+
|
|
68
|
+
optional arguments:
|
|
69
|
+
-h, --help show this help message and exit.
|
|
70
|
+
-V, --version display version information and exit.
|
|
71
|
+
-P, --python-regex PATTERN is a Python regular expression. This is the default.
|
|
72
|
+
-F, --fixed-strings interpret PATTERN as fixed strings, not regular expressions.
|
|
73
|
+
-i, --ignore-case ignore case distinctions.
|
|
74
|
+
-w, --word-regexp force PATTERN to match only whole words.
|
|
75
|
+
-c, --count print only a count of matches per file.
|
|
76
|
+
-r, --recursive search directories recursively.
|
|
77
|
+
-H, --with-filename print the file name for each match.
|
|
78
|
+
-N, --with-sheetname print the sheet name for each match.
|
|
79
|
+
-l, --files-with-match print only names of FILEs with match pattern.
|
|
80
|
+
-L, --files-without-match print only names of FILEs with no match pattern.
|
|
81
|
+
-S SEPARATOR, --separator SEPARATOR define custom list separator for output, the
|
|
82
|
+
default is TAB.
|
|
83
|
+
-Z, --null output a zero byte (the ASCII NUL character) instead of the
|
|
84
|
+
usual newline.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Examples:
|
|
89
|
+
```sh
|
|
90
|
+
xlsxgrep -i "foo" foobar.xlsx
|
|
91
|
+
```
|
|
92
|
+
```sh
|
|
93
|
+
xlsxgrep -c -H "(?i)foo|bar" /folder
|
|
94
|
+
```
|
|
95
|
+
## Installation
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
pip install xlsxgrep
|
|
99
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
## Owerview
|
|
2
|
+
|
|
3
|
+
*xlsxgrep* is a CLI tool to search text in XLSX, XLS, XLSM, CSV, TSV and ODS files. It works similarly to Unix/GNU Linux *grep*.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Grep compatible: xlsxgrep tries to be compatible with Unix/Linux grep, where it makes sense.
|
|
8
|
+
Some of grep options are supported (such as `-r`, `-i` or `-c`).
|
|
9
|
+
|
|
10
|
+
- Search many XLSX, XLS, XLSM, CSV, TSV and ODS files at once, even recursively in directories.
|
|
11
|
+
|
|
12
|
+
- Regular expressions: Python regex.
|
|
13
|
+
|
|
14
|
+
- Supported file types: csv, ods, tsv, xls, xlsx, xlsm.
|
|
15
|
+
|
|
16
|
+
- Works on all major platforms: Windows, macOS, BSD and Linux,
|
|
17
|
+
|
|
18
|
+
## Usage:
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
usage: xlsxgrep [-h] [-V] [-P] [-F] [-i] [-w] [-c] [-r] [-H] [-N] [-l] [-L] [-S SEPARATOR]
|
|
22
|
+
[-Z] [-d] PATTERN FILE [FILE ...]
|
|
23
|
+
|
|
24
|
+
positional arguments:
|
|
25
|
+
PATTERN use PATTERN as the pattern to search for.
|
|
26
|
+
FILE file or folder location.
|
|
27
|
+
|
|
28
|
+
optional arguments:
|
|
29
|
+
-h, --help show this help message and exit.
|
|
30
|
+
-V, --version display version information and exit.
|
|
31
|
+
-P, --python-regex PATTERN is a Python regular expression. This is the default.
|
|
32
|
+
-F, --fixed-strings interpret PATTERN as fixed strings, not regular expressions.
|
|
33
|
+
-i, --ignore-case ignore case distinctions.
|
|
34
|
+
-w, --word-regexp force PATTERN to match only whole words.
|
|
35
|
+
-c, --count print only a count of matches per file.
|
|
36
|
+
-r, --recursive search directories recursively.
|
|
37
|
+
-H, --with-filename print the file name for each match.
|
|
38
|
+
-N, --with-sheetname print the sheet name for each match.
|
|
39
|
+
-l, --files-with-match print only names of FILEs with match pattern.
|
|
40
|
+
-L, --files-without-match print only names of FILEs with no match pattern.
|
|
41
|
+
-S SEPARATOR, --separator SEPARATOR define custom list separator for output, the
|
|
42
|
+
default is TAB.
|
|
43
|
+
-Z, --null output a zero byte (the ASCII NUL character) instead of the
|
|
44
|
+
usual newline.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Examples:
|
|
49
|
+
```sh
|
|
50
|
+
xlsxgrep -i "foo" foobar.xlsx
|
|
51
|
+
```
|
|
52
|
+
```sh
|
|
53
|
+
xlsxgrep -c -H "(?i)foo|bar" /folder
|
|
54
|
+
```
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
pip install xlsxgrep
|
|
59
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = xlsxgrep
|
|
3
|
+
version = 0.0.32
|
|
4
|
+
author = Ivan Cvitic
|
|
5
|
+
author_email = cviticivan@gmail.com
|
|
6
|
+
license = MIT
|
|
7
|
+
license_files = LICENSE
|
|
8
|
+
description = CLI tool to search text in XLSX, XLS, XLSM, CSV, TSV and ODS files. It works similarly to Unix\GNU Linux grep.
|
|
9
|
+
url = https://github.com/zazuum/xlsxgrep
|
|
10
|
+
long_description = file: README.md
|
|
11
|
+
long_description_content_type = text/markdown
|
|
12
|
+
classifiers =
|
|
13
|
+
Environment :: Console
|
|
14
|
+
License :: OSI Approved :: MIT License
|
|
15
|
+
Intended Audience :: Developers
|
|
16
|
+
Intended Audience :: Education
|
|
17
|
+
Intended Audience :: System Administrators
|
|
18
|
+
Intended Audience :: Science/Research
|
|
19
|
+
Intended Audience :: End Users/Desktop
|
|
20
|
+
Operating System :: OS Independent
|
|
21
|
+
Programming Language :: Python :: 3
|
|
22
|
+
Programming Language :: Python :: 3.7
|
|
23
|
+
Programming Language :: Python :: 3.8
|
|
24
|
+
Programming Language :: Python :: 3.9
|
|
25
|
+
Programming Language :: Python :: 3.10
|
|
26
|
+
Programming Language :: Python :: 3.11
|
|
27
|
+
Programming Language :: Python :: 3.12
|
|
28
|
+
Programming Language :: Python :: 3.13
|
|
29
|
+
Programming Language :: Python :: 3.14
|
|
30
|
+
Topic :: Scientific/Engineering
|
|
31
|
+
Topic :: Scientific/Engineering :: Information Analysis
|
|
32
|
+
Topic :: Scientific/Engineering :: Bio-Informatics
|
|
33
|
+
Topic :: Office/Business
|
|
34
|
+
Topic :: Office/Business :: Financial
|
|
35
|
+
Topic :: Office/Business :: Financial :: Spreadsheet
|
|
36
|
+
Topic :: Utilities
|
|
37
|
+
|
|
38
|
+
[options]
|
|
39
|
+
packages = xlsxgrep
|
|
40
|
+
install_requires =
|
|
41
|
+
pyexcel
|
|
42
|
+
pyexcel-xls
|
|
43
|
+
pyexcel-xlsx
|
|
44
|
+
pyexcel-odsr
|
|
45
|
+
include_package_data = True
|
|
46
|
+
|
|
47
|
+
[options.entry_points]
|
|
48
|
+
console_scripts = xlsxgrep=xlsxgrep.xlsxgrep:main
|
|
49
|
+
|
|
50
|
+
[egg_info]
|
|
51
|
+
tag_build =
|
|
52
|
+
tag_date = 0
|
|
53
|
+
|
xlsxgrep-0.0.32/setup.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# This file is part of xlsxgrep, CLI tool to search text in XLSX, XLS, CSV, TSV and ODS files. It works similarly to Unix/GNU Linux grep.
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import argparse
|
|
6
|
+
import re
|
|
7
|
+
import warnings
|
|
8
|
+
import logging
|
|
9
|
+
import pyexcel as p
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import locale
|
|
12
|
+
from textwrap import dedent
|
|
13
|
+
|
|
14
|
+
__license__ = "MIT"
|
|
15
|
+
__version__ = "0.0.32"
|
|
16
|
+
__author__ = "Ivan Cvitic"
|
|
17
|
+
__email__ = "cviticivan@gmail.com"
|
|
18
|
+
VERSION_INFO = [
|
|
19
|
+
"xlsxgrep version: {0}".format(__version__),
|
|
20
|
+
"Python version: {0}".format(
|
|
21
|
+
" ".join(line.strip() for line in sys.version.splitlines())
|
|
22
|
+
),
|
|
23
|
+
"Locale: {0}".format(".".join(str(s) for s in locale.getlocale())),
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def main():
|
|
28
|
+
|
|
29
|
+
help_text = """positional arguments:
|
|
30
|
+
PATTERN use PATTERN as the pattern to search for.
|
|
31
|
+
FILE file or path to folder
|
|
32
|
+
|
|
33
|
+
options:
|
|
34
|
+
-h, --help show this help message and exit.
|
|
35
|
+
-V, --version display version information and exit.
|
|
36
|
+
-P, --python-regex PATTERN is a Python regular expression. This is the default.
|
|
37
|
+
-F, --fixed-strings interpret PATTERN as fixed strings, not regular expressions.
|
|
38
|
+
-i, --ignore-case ignore case distinctions.
|
|
39
|
+
-w, --word-regexp force PATTERN to match only whole words.
|
|
40
|
+
-c, --count print only a count of matches per file.
|
|
41
|
+
-r, --recursive search directories recursively.
|
|
42
|
+
-H, --with-filename print the file name for each match.
|
|
43
|
+
-N, --with-sheetname print the sheet name for each match.
|
|
44
|
+
-l, --files-with-match print only names of FILEs with match pattern.
|
|
45
|
+
-L, --files-without-match print only names of FILEs with no match pattern.
|
|
46
|
+
-S, --separator SEPARATOR define custom list separator for output, the default is TAB.
|
|
47
|
+
-Z, --null output a zero byte (the ASCII NUL character) instead of the
|
|
48
|
+
usual newline.
|
|
49
|
+
|
|
50
|
+
examples:
|
|
51
|
+
xlsxgrep -i "foo" foobar.xlsx
|
|
52
|
+
xlsxgrep -c -H "(?i)foo|bar" /folder"""
|
|
53
|
+
parser = argparse.ArgumentParser(
|
|
54
|
+
add_help=False, # epilog=example_text,
|
|
55
|
+
description=dedent(help_text),
|
|
56
|
+
prog="xlsxgrep",
|
|
57
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
58
|
+
usage=dedent(
|
|
59
|
+
"""
|
|
60
|
+
xlsxgrep [-h] [-V] [-P] [-F] [-i] [-w] [-c] [-r] [-H] [-N] [-l] [-L] [-S SEPARATOR]
|
|
61
|
+
[-Z] [-d] PATTTERN FILE [FILE ...]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
).strip(),
|
|
66
|
+
)
|
|
67
|
+
parser.add_argument(
|
|
68
|
+
"-h", "--help", action="help", help=argparse.SUPPRESS
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"PATTERN", help=argparse.SUPPRESS, type=str
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
"-V",
|
|
75
|
+
"--version",
|
|
76
|
+
help=argparse.SUPPRESS,
|
|
77
|
+
# help="display version information and exit.",
|
|
78
|
+
action="version",
|
|
79
|
+
version=dedent("\n".join(VERSION_INFO) + "\n"),
|
|
80
|
+
)
|
|
81
|
+
parser.add_argument(
|
|
82
|
+
"FILE", help=argparse.SUPPRESS, nargs="+", action="append",
|
|
83
|
+
)
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"-P",
|
|
86
|
+
"--python-regex",
|
|
87
|
+
help=argparse.SUPPRESS,
|
|
88
|
+
# help="PATTERN is a Python regular expression. This is the default.",
|
|
89
|
+
required=False,
|
|
90
|
+
action="store_true",
|
|
91
|
+
default=False,
|
|
92
|
+
)
|
|
93
|
+
parser.add_argument(
|
|
94
|
+
"-F",
|
|
95
|
+
"--fixed-strings",
|
|
96
|
+
help=argparse.SUPPRESS,
|
|
97
|
+
# help="interpret PATTERN as fixed strings, not regular expressions.",
|
|
98
|
+
required=False,
|
|
99
|
+
action="store_true",
|
|
100
|
+
default=False,
|
|
101
|
+
)
|
|
102
|
+
parser.add_argument(
|
|
103
|
+
"-i",
|
|
104
|
+
"--ignore-case",
|
|
105
|
+
help=argparse.SUPPRESS,
|
|
106
|
+
# help="ignore case distinctions.",
|
|
107
|
+
required=False,
|
|
108
|
+
action="store_true",
|
|
109
|
+
)
|
|
110
|
+
parser.add_argument(
|
|
111
|
+
"-w",
|
|
112
|
+
"--word-regexp",
|
|
113
|
+
help=argparse.SUPPRESS,
|
|
114
|
+
# help="force PATTERN to match only whole words.",
|
|
115
|
+
required=False,
|
|
116
|
+
action="store_true",
|
|
117
|
+
)
|
|
118
|
+
parser.add_argument(
|
|
119
|
+
"-c",
|
|
120
|
+
"--count",
|
|
121
|
+
help=argparse.SUPPRESS,
|
|
122
|
+
# help="print only a count of matches per file.",
|
|
123
|
+
required=False,
|
|
124
|
+
action="store_true",
|
|
125
|
+
)
|
|
126
|
+
parser.add_argument(
|
|
127
|
+
"-r",
|
|
128
|
+
"--recursive",
|
|
129
|
+
help=argparse.SUPPRESS,
|
|
130
|
+
# help="search directories recursively.",
|
|
131
|
+
required=False,
|
|
132
|
+
action="store_true",
|
|
133
|
+
)
|
|
134
|
+
parser.add_argument(
|
|
135
|
+
"-H",
|
|
136
|
+
"--with-filename",
|
|
137
|
+
help=argparse.SUPPRESS,
|
|
138
|
+
# help="print the file name for each match.",
|
|
139
|
+
required=False,
|
|
140
|
+
action="store_true",
|
|
141
|
+
)
|
|
142
|
+
parser.add_argument(
|
|
143
|
+
"-N",
|
|
144
|
+
"--with-sheetname",
|
|
145
|
+
help=argparse.SUPPRESS,
|
|
146
|
+
# help="print the sheet name for each match.",
|
|
147
|
+
required=False,
|
|
148
|
+
action="store_true",
|
|
149
|
+
)
|
|
150
|
+
parser.add_argument(
|
|
151
|
+
"-l",
|
|
152
|
+
"--files-with-match",
|
|
153
|
+
help=argparse.SUPPRESS,
|
|
154
|
+
# help="print only names of FILEs with match pattern.",
|
|
155
|
+
required=False,
|
|
156
|
+
action="store_true",
|
|
157
|
+
)
|
|
158
|
+
parser.add_argument(
|
|
159
|
+
"-L",
|
|
160
|
+
"--files-without-match",
|
|
161
|
+
help=argparse.SUPPRESS,
|
|
162
|
+
# help="print only names of FILEs with no match pattern.",
|
|
163
|
+
required=False,
|
|
164
|
+
action="store_true",
|
|
165
|
+
)
|
|
166
|
+
parser.add_argument(
|
|
167
|
+
"-S",
|
|
168
|
+
"--separator",
|
|
169
|
+
# help="define custom list separator for output, the default is TAB.",
|
|
170
|
+
help=argparse.SUPPRESS,
|
|
171
|
+
required=False,
|
|
172
|
+
default="\t",
|
|
173
|
+
type=str,
|
|
174
|
+
)
|
|
175
|
+
parser.add_argument(
|
|
176
|
+
"-Z",
|
|
177
|
+
"--null",
|
|
178
|
+
help=argparse.SUPPRESS,
|
|
179
|
+
# help="output a zero byte (the ASCII NUL character) instead of the usual newline.",
|
|
180
|
+
required=False,
|
|
181
|
+
action="store_true",
|
|
182
|
+
)
|
|
183
|
+
parser.add_argument(
|
|
184
|
+
"-d",
|
|
185
|
+
"--debug",
|
|
186
|
+
help=argparse.SUPPRESS,
|
|
187
|
+
required=False,
|
|
188
|
+
default=False,
|
|
189
|
+
action="store_true",
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
if len(sys.argv) == 1:
|
|
193
|
+
parser.print_usage(sys.stderr)
|
|
194
|
+
print("Type 'xlsxgrep --help' for more information.")
|
|
195
|
+
sys.exit(1)
|
|
196
|
+
|
|
197
|
+
args = parser.parse_args()
|
|
198
|
+
|
|
199
|
+
def ActivateDebug():
|
|
200
|
+
if args.debug == False:
|
|
201
|
+
# Some debug options
|
|
202
|
+
# - Supress unsupported file extensions warnings.
|
|
203
|
+
# 'UserWarning: Data Validation extension is not supported and will be removed'. (module=openpyxl)
|
|
204
|
+
# 'UserWarning: Unknown extension is not supported and will be removed'. (module=openpyxl)
|
|
205
|
+
warnings.filterwarnings(
|
|
206
|
+
"ignore",
|
|
207
|
+
category=UserWarning,
|
|
208
|
+
message="Unknown extension is not supported and will be removed",
|
|
209
|
+
)
|
|
210
|
+
warnings.filterwarnings(
|
|
211
|
+
"ignore",
|
|
212
|
+
category=UserWarning,
|
|
213
|
+
message="Data Validation extension is not supported and will be removed",
|
|
214
|
+
)
|
|
215
|
+
# - Ignore deprecated python regex warnings.
|
|
216
|
+
# 'DeprecationWarning: Flags not at the start of the expression 'foo|(?i)bar'. (module=re)
|
|
217
|
+
warnings.filterwarnings(
|
|
218
|
+
"ignore",
|
|
219
|
+
category=DeprecationWarning,
|
|
220
|
+
message=".*Flags not at the start of the expression*.",
|
|
221
|
+
)
|
|
222
|
+
# - Supress Conditional Formatting extension not supported and Cannot parse header or footer warning.
|
|
223
|
+
warnings.filterwarnings(
|
|
224
|
+
"ignore",
|
|
225
|
+
category=UserWarning,
|
|
226
|
+
message="Conditional Formatting extension is not supported and will be removed",
|
|
227
|
+
)
|
|
228
|
+
warnings.filterwarnings(
|
|
229
|
+
"ignore",
|
|
230
|
+
category=UserWarning,
|
|
231
|
+
message="Cannot parse header or footer so it will be ignored",
|
|
232
|
+
)
|
|
233
|
+
# - Disable all warnings in openpyxl
|
|
234
|
+
warnings.filterwarnings(
|
|
235
|
+
"ignore", category=UserWarning, module="openpyxl")
|
|
236
|
+
# - Disable all logging warnings
|
|
237
|
+
logging.disable(logging.WARNING)
|
|
238
|
+
else:
|
|
239
|
+
print("--version info: "+" ".join(VERSION_INFO))
|
|
240
|
+
|
|
241
|
+
pass
|
|
242
|
+
|
|
243
|
+
ActivateDebug()
|
|
244
|
+
|
|
245
|
+
# Valid Python Regex Check ( Optional Argument -P, --python-regex)
|
|
246
|
+
|
|
247
|
+
def Check_Python_Regex():
|
|
248
|
+
if args.fixed_strings or args.ignore_case or args.word_regexp:
|
|
249
|
+
if args.python_regex == True:
|
|
250
|
+
sys.exit(
|
|
251
|
+
"xlsxgrep: --python-regex cannot be used together with: -F, -w or -i"
|
|
252
|
+
)
|
|
253
|
+
else:
|
|
254
|
+
args.python_regex = False
|
|
255
|
+
return args.python_regex
|
|
256
|
+
|
|
257
|
+
else:
|
|
258
|
+
try:
|
|
259
|
+
args.python_regex = True
|
|
260
|
+
re.compile(args.PATTERN)
|
|
261
|
+
pass
|
|
262
|
+
except re.error:
|
|
263
|
+
exit(
|
|
264
|
+
"Error: Not valid Python Regular Expression. For fixed strings use flag: -F"
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
Check_Python_Regex()
|
|
268
|
+
|
|
269
|
+
# Checking file or folder format and destination
|
|
270
|
+
|
|
271
|
+
def File_And_Path_Location():
|
|
272
|
+
File_List = []
|
|
273
|
+
fileTypes = (
|
|
274
|
+
".xls",
|
|
275
|
+
".XLS",
|
|
276
|
+
".xlsx",
|
|
277
|
+
".XLSX",
|
|
278
|
+
".ods",
|
|
279
|
+
".ODS",
|
|
280
|
+
".csv",
|
|
281
|
+
".CSV",
|
|
282
|
+
".tsv",
|
|
283
|
+
".TSV",
|
|
284
|
+
".xlsm",
|
|
285
|
+
".XLSM",
|
|
286
|
+
)
|
|
287
|
+
for i in args.FILE[0]:
|
|
288
|
+
|
|
289
|
+
if (Path(i).is_file() is False) and (Path(i).is_dir() is False):
|
|
290
|
+
exit(str(i) + " File or folder not found. ")
|
|
291
|
+
|
|
292
|
+
elif Path(i).is_file() and str(Path(i)).endswith(fileTypes):
|
|
293
|
+
File_List.append(str(Path(i)))
|
|
294
|
+
|
|
295
|
+
elif Path(i).is_dir():
|
|
296
|
+
if args.recursive == True:
|
|
297
|
+
for child in Path(i).rglob("*"):
|
|
298
|
+
if str(child).endswith(fileTypes):
|
|
299
|
+
File_List.append(str(child))
|
|
300
|
+
else:
|
|
301
|
+
for child in Path(i).iterdir():
|
|
302
|
+
if str(child).endswith(fileTypes):
|
|
303
|
+
File_List.append(str(child))
|
|
304
|
+
|
|
305
|
+
elif (Path(i).is_file() and str(Path(i)).endswith(fileTypes)) == False:
|
|
306
|
+
# perform file check
|
|
307
|
+
print("Error: Unsupported file format: ",
|
|
308
|
+
Path(i), file=sys.stderr)
|
|
309
|
+
|
|
310
|
+
SEARCH(File_List)
|
|
311
|
+
|
|
312
|
+
# Checking pattern optional arguments ("-P", '--python-regex', "-w", '--word-regexp')
|
|
313
|
+
|
|
314
|
+
def Check_Optional_Args(val):
|
|
315
|
+
|
|
316
|
+
if args.python_regex == True:
|
|
317
|
+
return re.search(r"%s" % args.PATTERN, str(val))
|
|
318
|
+
|
|
319
|
+
elif args.word_regexp == True:
|
|
320
|
+
if args.ignore_case == True:
|
|
321
|
+
return str(args.PATTERN).upper() == (str(val).upper())
|
|
322
|
+
else:
|
|
323
|
+
return args.PATTERN == (str(val))
|
|
324
|
+
|
|
325
|
+
elif args.word_regexp == False:
|
|
326
|
+
if args.ignore_case == False:
|
|
327
|
+
return args.PATTERN == args.PATTERN in (str(val))
|
|
328
|
+
else:
|
|
329
|
+
return str(args.PATTERN).upper() in (str(val).upper())
|
|
330
|
+
else:
|
|
331
|
+
return print("...Some Error Occured...(optional arguments!?)")
|
|
332
|
+
|
|
333
|
+
# Checking output optional arguments ("-H", '--with-filename', "-N", '--with-sheetname')
|
|
334
|
+
|
|
335
|
+
def Show_Filename_And_Sheetname(file, active_sheet, linesArray):
|
|
336
|
+
ENDSWITH = "\n"
|
|
337
|
+
if args.null:
|
|
338
|
+
ENDSWITH = ""
|
|
339
|
+
|
|
340
|
+
if args.count == True:
|
|
341
|
+
pass
|
|
342
|
+
|
|
343
|
+
elif args.files_with_match:
|
|
344
|
+
pass
|
|
345
|
+
|
|
346
|
+
elif args.files_without_match:
|
|
347
|
+
pass
|
|
348
|
+
|
|
349
|
+
elif args.with_filename == True:
|
|
350
|
+
if args.with_sheetname == True:
|
|
351
|
+
return print(
|
|
352
|
+
file
|
|
353
|
+
+ ": "
|
|
354
|
+
+ active_sheet
|
|
355
|
+
+ ": "
|
|
356
|
+
+ str(args.separator)
|
|
357
|
+
+ str(args.separator).join(map(str, linesArray)),
|
|
358
|
+
end=ENDSWITH,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
elif args.with_sheetname == False:
|
|
362
|
+
return print(
|
|
363
|
+
file + ": " + str(args.separator) +
|
|
364
|
+
str(args.separator).join(map(str, linesArray)),
|
|
365
|
+
end=ENDSWITH,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
elif args.with_filename == False:
|
|
369
|
+
if args.with_sheetname == True:
|
|
370
|
+
return print(
|
|
371
|
+
active_sheet
|
|
372
|
+
+ ": "
|
|
373
|
+
+ str(args.separator)
|
|
374
|
+
+ str(args.separator).join(map(str, linesArray)),
|
|
375
|
+
end=ENDSWITH,
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
else:
|
|
379
|
+
print(*linesArray, sep=str(args.separator), end=ENDSWITH)
|
|
380
|
+
|
|
381
|
+
# Iterate over rows and columns and append matches count to array.
|
|
382
|
+
|
|
383
|
+
SumOfROW, SumOfCELL, SumOfSTR = [], [], []
|
|
384
|
+
|
|
385
|
+
def Iterate_Over_Cells(book, file):
|
|
386
|
+
ROWcount, CELLcount, STRcount = [0], [0], [0]
|
|
387
|
+
for key, item in book.items():
|
|
388
|
+
for line in item:
|
|
389
|
+
AuxFlag = False
|
|
390
|
+
for cell in line:
|
|
391
|
+
if Check_Optional_Args(cell):
|
|
392
|
+
if args.count:
|
|
393
|
+
AuxFlag = True
|
|
394
|
+
CELLcount[0] = CELLcount[0] + 1
|
|
395
|
+
reESCapedQuery = re.escape(
|
|
396
|
+
str(args.PATTERN).upper())
|
|
397
|
+
STRcell = str(cell).upper()
|
|
398
|
+
if args.python_regex == False:
|
|
399
|
+
for x in re.findall(reESCapedQuery, STRcell):
|
|
400
|
+
STRcount[0] = STRcount[0] + 1
|
|
401
|
+
|
|
402
|
+
else:
|
|
403
|
+
for x in re.findall(str(args.PATTERN), str(cell)):
|
|
404
|
+
STRcount[0] = STRcount[0] + 1
|
|
405
|
+
else:
|
|
406
|
+
AuxFlag = True
|
|
407
|
+
ROWcount[0] = ROWcount[0] - 1
|
|
408
|
+
|
|
409
|
+
if AuxFlag == True:
|
|
410
|
+
ROWcount[0] = ROWcount[0] + 1
|
|
411
|
+
|
|
412
|
+
Show_Filename_And_Sheetname(file, key, line)
|
|
413
|
+
|
|
414
|
+
if ROWcount[0] > 0:
|
|
415
|
+
ENDSWITH = "\n"
|
|
416
|
+
ROWS, CELLS, STRINGS = ROWcount, CELLcount, STRcount
|
|
417
|
+
if args.null:
|
|
418
|
+
ENDSWITH = ""
|
|
419
|
+
if args.with_sheetname or args.with_filename:
|
|
420
|
+
print(
|
|
421
|
+
file,
|
|
422
|
+
":",
|
|
423
|
+
ROWS[0],
|
|
424
|
+
"Rows, ",
|
|
425
|
+
CELLS[0],
|
|
426
|
+
"Cells, ",
|
|
427
|
+
STRINGS[0],
|
|
428
|
+
"Strings",
|
|
429
|
+
end=ENDSWITH,
|
|
430
|
+
)
|
|
431
|
+
SumOfCELL.extend(CELLcount)
|
|
432
|
+
SumOfSTR.extend(STRcount)
|
|
433
|
+
SumOfROW.extend(ROWcount)
|
|
434
|
+
|
|
435
|
+
# Check files-with-match and files-without-match arguments
|
|
436
|
+
|
|
437
|
+
def HyphenlAndHyphenLCheck(book, file):
|
|
438
|
+
ENDSWITH = "\n"
|
|
439
|
+
if args.null:
|
|
440
|
+
ENDSWITH = ""
|
|
441
|
+
|
|
442
|
+
if args.files_with_match:
|
|
443
|
+
if Check_Optional_Args(book):
|
|
444
|
+
return print(file, end=ENDSWITH)
|
|
445
|
+
|
|
446
|
+
elif args.files_without_match:
|
|
447
|
+
if not Check_Optional_Args(book):
|
|
448
|
+
return print(file, end=ENDSWITH)
|
|
449
|
+
|
|
450
|
+
else:
|
|
451
|
+
|
|
452
|
+
Iterate_Over_Cells(book, file)
|
|
453
|
+
|
|
454
|
+
# Count matches. Rows, cells and strings.
|
|
455
|
+
|
|
456
|
+
def SumOfRowsCellsAndStrings():
|
|
457
|
+
ROWS, CELLS, STRINGS = sum(SumOfROW), sum(SumOfCELL), sum(SumOfSTR)
|
|
458
|
+
print("Search results: ", ROWS, "Rows, ",
|
|
459
|
+
CELLS, "Cells, ", STRINGS, "Strings")
|
|
460
|
+
|
|
461
|
+
# Opening files, start searching
|
|
462
|
+
|
|
463
|
+
def SEARCH(File_List):
|
|
464
|
+
for file in File_List:
|
|
465
|
+
try:
|
|
466
|
+
if args.debug == True:
|
|
467
|
+
warnings.resetwarnings()
|
|
468
|
+
print("-- debug mode: " + file)
|
|
469
|
+
|
|
470
|
+
if file.endswith((".xlsx", ".XLSX", ".xlsm", ".XLSM")):
|
|
471
|
+
book = p.get_book_dict(
|
|
472
|
+
file_name=file, skip_hidden_row_and_column=False
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
else:
|
|
476
|
+
book = p.get_book_dict(
|
|
477
|
+
file_name=file,
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
HyphenlAndHyphenLCheck(book, file)
|
|
481
|
+
|
|
482
|
+
except KeyboardInterrupt:
|
|
483
|
+
|
|
484
|
+
sys.exit(0)
|
|
485
|
+
|
|
486
|
+
except:
|
|
487
|
+
print(
|
|
488
|
+
f"Error:\tUnsupported format, password protected or corrupted file: {file}",
|
|
489
|
+
file=sys.stderr,
|
|
490
|
+
)
|
|
491
|
+
pass
|
|
492
|
+
|
|
493
|
+
if args.count:
|
|
494
|
+
if args.files_with_match or args.files_without_match:
|
|
495
|
+
pass
|
|
496
|
+
|
|
497
|
+
else:
|
|
498
|
+
SumOfRowsCellsAndStrings()
|
|
499
|
+
|
|
500
|
+
File_And_Path_Location()
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
if __name__ == "__main__":
|
|
504
|
+
main()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xlsxgrep
|
|
3
|
+
Version: 0.0.32
|
|
4
|
+
Summary: CLI tool to search text in XLSX, XLS, XLSM, CSV, TSV and ODS files. It works similarly to Unix\GNU Linux grep.
|
|
5
|
+
Home-page: https://github.com/zazuum/xlsxgrep
|
|
6
|
+
Author: Ivan Cvitic
|
|
7
|
+
Author-email: cviticivan@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Education
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering
|
|
27
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
28
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
29
|
+
Classifier: Topic :: Office/Business
|
|
30
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
31
|
+
Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
|
|
32
|
+
Classifier: Topic :: Utilities
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: pyexcel
|
|
36
|
+
Requires-Dist: pyexcel-xls
|
|
37
|
+
Requires-Dist: pyexcel-xlsx
|
|
38
|
+
Requires-Dist: pyexcel-odsr
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
## Owerview
|
|
42
|
+
|
|
43
|
+
*xlsxgrep* is a CLI tool to search text in XLSX, XLS, XLSM, CSV, TSV and ODS files. It works similarly to Unix/GNU Linux *grep*.
|
|
44
|
+
|
|
45
|
+
## Features
|
|
46
|
+
|
|
47
|
+
- Grep compatible: xlsxgrep tries to be compatible with Unix/Linux grep, where it makes sense.
|
|
48
|
+
Some of grep options are supported (such as `-r`, `-i` or `-c`).
|
|
49
|
+
|
|
50
|
+
- Search many XLSX, XLS, XLSM, CSV, TSV and ODS files at once, even recursively in directories.
|
|
51
|
+
|
|
52
|
+
- Regular expressions: Python regex.
|
|
53
|
+
|
|
54
|
+
- Supported file types: csv, ods, tsv, xls, xlsx, xlsm.
|
|
55
|
+
|
|
56
|
+
- Works on all major platforms: Windows, macOS, BSD and Linux,
|
|
57
|
+
|
|
58
|
+
## Usage:
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
usage: xlsxgrep [-h] [-V] [-P] [-F] [-i] [-w] [-c] [-r] [-H] [-N] [-l] [-L] [-S SEPARATOR]
|
|
62
|
+
[-Z] [-d] PATTERN FILE [FILE ...]
|
|
63
|
+
|
|
64
|
+
positional arguments:
|
|
65
|
+
PATTERN use PATTERN as the pattern to search for.
|
|
66
|
+
FILE file or folder location.
|
|
67
|
+
|
|
68
|
+
optional arguments:
|
|
69
|
+
-h, --help show this help message and exit.
|
|
70
|
+
-V, --version display version information and exit.
|
|
71
|
+
-P, --python-regex PATTERN is a Python regular expression. This is the default.
|
|
72
|
+
-F, --fixed-strings interpret PATTERN as fixed strings, not regular expressions.
|
|
73
|
+
-i, --ignore-case ignore case distinctions.
|
|
74
|
+
-w, --word-regexp force PATTERN to match only whole words.
|
|
75
|
+
-c, --count print only a count of matches per file.
|
|
76
|
+
-r, --recursive search directories recursively.
|
|
77
|
+
-H, --with-filename print the file name for each match.
|
|
78
|
+
-N, --with-sheetname print the sheet name for each match.
|
|
79
|
+
-l, --files-with-match print only names of FILEs with match pattern.
|
|
80
|
+
-L, --files-without-match print only names of FILEs with no match pattern.
|
|
81
|
+
-S SEPARATOR, --separator SEPARATOR define custom list separator for output, the
|
|
82
|
+
default is TAB.
|
|
83
|
+
-Z, --null output a zero byte (the ASCII NUL character) instead of the
|
|
84
|
+
usual newline.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Examples:
|
|
89
|
+
```sh
|
|
90
|
+
xlsxgrep -i "foo" foobar.xlsx
|
|
91
|
+
```
|
|
92
|
+
```sh
|
|
93
|
+
xlsxgrep -c -H "(?i)foo|bar" /folder
|
|
94
|
+
```
|
|
95
|
+
## Installation
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
pip install xlsxgrep
|
|
99
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
setup.cfg
|
|
6
|
+
setup.py
|
|
7
|
+
xlsxgrep/__init__.py
|
|
8
|
+
xlsxgrep/xlsxgrep.py
|
|
9
|
+
xlsxgrep.egg-info/PKG-INFO
|
|
10
|
+
xlsxgrep.egg-info/SOURCES.txt
|
|
11
|
+
xlsxgrep.egg-info/dependency_links.txt
|
|
12
|
+
xlsxgrep.egg-info/entry_points.txt
|
|
13
|
+
xlsxgrep.egg-info/requires.txt
|
|
14
|
+
xlsxgrep.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
xlsxgrep
|