Python与Perl中的低级脚本

alv*_*vas 11 python string perl file lowercase

在Perl中,为了小写文本文件,我可以执行以下操作lowercase.perl:

#!/usr/bin/env perl

use warnings;
use strict;

binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");

while(<STDIN>) {
  print lc($_);
}
Run Code Online (Sandbox Code Playgroud)

并在命令行上: perl lowercase.perl < infile.txt > lowered.txt

Python,我可以做lowercase.py:

#!/usr/bin/env python
import io
import sys

with io.open(sys.argv[1], 'r', 'utf8') as fin:
    with io.open(sys.argv[2], 'r', 'utf8') as fout:
        fout.write(fin.read().lower())
Run Code Online (Sandbox Code Playgroud)

并在命令行上: python lowercase.py infile.txt lowered.txt

Perl lowercase.perl与Python有lowercase.py什么不同?

是否输出输入并在输出时将其小写?或者它是否像Python一样读取整个文件lowercase.py

有没有一种方法可以将输入流式传输到Python并逐字节输出降低的大小写或者通过char输出char?

有没有办法控制命令行语法,使其遵循Perl STDIN和STDOUT?比如python lowercase.py < infile.txt > lowered.txt

小智 7

您的Perl代码的Python 3.x等价物可能如下所示:

#!/usr/bin/env python3.4
import sys

for line in sys.stdin:
    print(line[:-1].lower(), file=sys.stdout)
Run Code Online (Sandbox Code Playgroud)

它逐行读取stdin,可以在shell管道中使用


zdi*_*dim 3

这里似乎有两个交叉的问题,我首先解决这个问题。有关如何使 Perl 和 Python 使用具有非常相似行为的调用,请参阅本文的第二部分。

简而言之:它们的 I/O方式有所不同,但都是逐行工作,而且 Python 代码很容易更改,以允许与 Perl 代码相同的命令行调用。此外,两者都可以编写为允许来自文件或标准输入流的输入。


(1) 您的两个解决方案都是“流式”,即它们都逐行处理输入。Perl 代码读取自STDIN文件中读取数据,而 Python 代码从文件中获取数据,但它们每次都获取一行。从这个意义上说,它们在处理大文件时的效率是相当的。

在 Python 中逐行读取和写入文件的标准方法是

with open('infile', 'r') as fin, open('outfile', 'w') as fout:
    fout.write(fin.read().lower())
Run Code Online (Sandbox Code Playgroud)

例如,请参阅这些有关处理非常大的文件读写文件的SO 帖子。您读取文件的方式似乎是逐行处理的惯用方式,例如,请参阅关于逐行读取大文件惯用逐行读取和另一篇关于逐行读取的帖子。

将此处的第一个打开更改为您的io.open,以直接从命令行获取第一个参数作为文件名,并根据需要添加模式。

(2) 您显示的具有输入和输出重定向的命令行是 shell 功能

./program < input > output
Run Code Online (Sandbox Code Playgroud)

program通过标准输入流(文件描述符 0)馈送行。input它们是由 shell 通过< 重定向从文件中提供的。来自gnu bash 手册(参见 3.6.1),其中“ word ”代表我们的“ input

输入重定向会导致名称由字扩展产生的文件打开以在文件描述符 n 上读取,如果未指定 n 则在标准输入(文件描述符 0)上读取。

可以编写任何程序来做到这一点,即。充当过滤器。对于Python,你可以使用

import sys   
for line in sys.stdin:
    print line.lower()
Run Code Online (Sandbox Code Playgroud)

例如,请参阅有关编写过滤器的帖子。script.py < input现在您可以像在 shell 中一样调用它。

代码print发送到标准输出,然后 shell 可以使用>. 然后您将获得与 Perl 脚本相同的调用。

我认为>这两种情况下的标准输出重定向都是明确的。


最后,您可以通过这种方式使两者具有几乎相同的行为,并允许任一调用。

在 Perl 中,有以下习惯用法

while (my $line = <>) {
    # process $line
}
Run Code Online (Sandbox Code Playgroud)

菱形运算符 <>要么从命令行上提交的所有文件中逐行获取(可在 中找到@ARGV),要么从中获取其行STDIN(如果数据以某种方式通过管道传输到脚本中)。来自perlop 中的 I/O 运算符

空文件句柄<>很特殊:它可用于模拟 sed 和 awk 以及任何其他采用文件名列表的 Unix 过滤程序的行为,对所有文件名的每一行输入执行相同的操作。输入<>来自标准输入,或来自命令行上列出的每个文件。它的工作原理如下:第一次<>求值,@ARGV检查数组,如果它为空,$ARGV[0]则设置为"-",打开时为您提供标准输入。然后将该数组@ARGV作为文件名列表进行处理。

在 Python 中,你可以通过以下方式获得几乎相同的行为

import fileinput
for line in fileinput.input():
    # process line
Run Code Online (Sandbox Code Playgroud)

这也会遍历名为 in 的文件行sys.argv,默认sys.stdin情况下列表为空。来自文件输入文档

这会迭代 中列出的所有文件的行sys.argv[1:],默认sys.stdin情况下列表为空。如果文件名是'-',它也会被替换为sys.stdin. 要指定备用文件名列表,请将其作为第一个参数传递给input(). 也允许使用单个文件名。

在这两种情况下,如果存在文件名以外的命令行参数,则需要做更多工作。

这样你就可以以任何一种方式使用 Perl 和 Python 脚本

lowercase < input > output
lowercase input   > output
Run Code Online (Sandbox Code Playgroud)

或者,就此而言,作为cat input | lowercase > output.


这里的所有方法都逐行读取输入并写入输出。这可以通过解释器、系统和 shell 的重定向进一步优化(缓冲)。可以改变它,以便以较小的块读取和/或写入,但这将非常低效并且明显减慢程序速度。