» Python创建命令行程序grep » 2. 开发 » 2.8 支持管道

支持管道

在类 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

其结果与上面相同。

上页下页