支持管道
在类 Unix 操作系统(如 Linux 和 macOS)中,管道是一种用于进程间通信(IPC)的机制,允许一个进程的输出被用作另一个进程的输入。
在 Shell 命令中,管道由 |
符号表示。当你使用类似 command1 | command2
的命令时,意味着 command1
的标准输出被连接到 command2
的标准输入。
例如:
cat file.txt | grep "pattern"
在此命令中,file.txt
的内容被作为输入传递到 grep
命令,该命令搜索指定的模式。
Windows 中也存在类似的机制,但它被称为管线。
例如:
Get-Content file.txt | Select-String "pattern"
在此 PowerShell 命令中,Get-Content
获取 file.txt
中的内容,并将其输出传递给 Select-String
进行模式匹配。
修改 grepy/cli.py 以使 file_path
参数变为可选:
parser.add_argument('pattern', type=str, help='The pattern to search for')
- parser.add_argument('file_path', type=str,
+ parser.add_argument('file_path', type=str, nargs="?", default="",
help='The path to the file to search in')
可以使用值为 '?'
的 nargs
参数添加可选的位置参数。这使得该参数是可选的,在命令行上提供不提供该参数皆可。
文件路径为空时无法做递归搜索,故修改 grepy/cli.py:
- if args.recursive:
+ if args.recursive and args.file_path != "":
result = grep_recursive(args.pattern,
args.file_path, get_options(args))
else:
在 grepy/grep.py
中,当 file_path
为空时,从标准输入读取内容:
def grep(pattern: Union[str, re.Pattern],
file_path: str, options: List[str] = []):
if not file_path: # 从stdin读取,通常是管道
lines = sys.stdin.read().split('\n')
else: # 从文件读取
with open(file_path, 'r') as file:
try:
lines = file.readlines()
except UnicodeDecodeError: # 过滤掉二进制文件
return {file_path: []}
if options:
if 'i' in options:
pattern = re.compile(pattern, re.IGNORECASE)
if 'v' in options:
matching_lines = _filter_lines(pattern, lines, False)
else:
matching_lines = _filter_lines(pattern, lines, True)
else:
matching_lines = _filter_lines(pattern, lines, True)
return {file_path: matching_lines}
现在可以执行以下操作:
cat grepy/cli.py | python3 -m grepy.cli -n result
其结果:
35: result = grep_recursive(args.pattern,
38: result = grep(args.pattern, args.file_path, get_options(args))
41: print(grep_count(result))
43: print_result(result, args.line_number)
55: def print_result(result: Dict[str, MatchResults], line_number_option: bool):
57: file_count = len(result)
58: for file_path, lines in result.items():
重新安装后,你的 grepy
也可以支持管道。
cat grepy/cli.py | grepy -n result
其结果与上面相同。