Python中的小写脚本vs P

2024-09-28 22:23:07 发布

您现在位置:Python中文网/ 问答频道 /正文

在Perl中,要将文本文件小写,我可以执行以下操作^{}

#!/usr/bin/env perl

use warnings;
use strict;

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

while(<STDIN>) {
  print lc($_);
}

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

Python中,我可以使用lowercase.py

^{pr2}$

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

Perllowercase.perl与Pythonlowercase.py不同吗?

它输出的流是小写的吗?还是像Python的lowercase.py那样读取整个文件?

是否有一种方法可以将输入流式传输到Python中,然后逐字节或逐字符输出小写的结果,而不是读取整个文件?

有没有一种方法可以控制命令行语法,使其遵循Perl STDIN和STDOUT?E、 g.python lowercase.py < infile.txt > lowered.txt?在


Tags: 文件命令行pytxtusestdinstdoututf8
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())

例如,请参见processing a very large file和{a2}上的这些SO帖子。对于逐行处理来说,您读取文件的方式似乎是惯用的方式,请参见例如在reading large-file line-by-line、在idiomatic line-by-line reading上发布以及在{a5}上发布另一篇文章。在

将first open here更改为io.open,以直接从命令行中获取第一个参数作为文件名,并根据需要添加模式。在

(2)您显示的带有输入和输出重定向的命令行是一个shell特性

^{pr2}$

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

Redirection of input causes the file whose name results from the expansion of word to be opened for reading on file descriptor n, or the standard input (file descriptor 0) if n is not specified.

任何一个程序都可以这样做,即充当一个过滤器。对于Python,可以使用

import sys   
for line in sys.stdin:
    print line.lower()

例如,请参阅writing filters上的帖子。现在您可以在shell中将其作为script.py < input调用。在

将代码print转换为标准输出,然后shell可以使用>将其重定向。然后得到与Perl脚本相同的调用。在

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


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

在Perl中,有以下习惯用法

while (my $line = <>) {
    # process $line
}

diamond运算符<>要么从命令行提交的所有文件中逐行获取(这些文件位于@ARGV),要么从STDIN获取行(如果数据以某种方式通过管道传输到脚本中)。从I/O Operators in perlop

The null filehandle <> is special: it can be used to emulate the behavior of sed and awk, and any other Unix filter program that takes a list of filenames, doing the same to each line of input from all of them. Input from <> comes either from standard input, or from each file listed on the command line. Here's how it works: the first time <> is evaluated, the @ARGV array is checked, and if it is empty, $ARGV[0] is set to "-" , which when opened gives you standard input. The @ARGV array is then processed as a list of filenames.

在Python中,通过

import fileinput
for line in fileinput.input():
    # process line

这还将遍历sys.argv中命名的文件行,如果列表为空,则默认为sys.stdin。来自fileinput文档

This iterates over the lines of all files listed in sys.argv[1:], defaulting to sys.stdin if the list is empty. If a filename is '-', it is also replaced by sys.stdin. To specify an alternative list of filenames, pass it as the first argument to input(). A single file name is also allowed.

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

有了它,您就可以以任何一种方式使用Perl和Python脚本

lowercase < input > output
lowercase input   > output

或者,在这个问题上,作为cat input | lowercase > output。在


这里的所有方法逐行读取输入和写入输出。解释器、系统和shell的重定向可以进一步优化(缓冲)这一点。可以将其改为以更小的块读和/或写,但这将是非常低效的,并且会显著地减慢程序的速度。在

有点偏离主题(取决于您对“Perl”的定义),但可能感兴趣。。。在

perl6 -e  ' .lc.say for "infile.txt".IO.lines ' > lowered.txt

这既不处理“逐字节”也不处理“整个文件”,而是“逐行处理”。.lines创建一个延迟列表,这样如果文件很大,就不会占用大量内存。文件被假定为文本(这意味着您在读取时得到Str,而不是Buf)的字节,编码默认为“Unicode”—意思是open将尝试找出使用了什么UTF,如果不能,它将假定UTF-8。详细信息here。在

默认情况下,行尾是chomp'的,当您阅读并由say放回原处时,如果处理要求禁止这样做,您可以将布尔命名参数:chomp传递给.lines(并使用.print,而不是{})

^{pr2}$

您可以避免IO重定向,并在perl6中完成所有操作,但这将将整个文件作为一个文件读入Str

$ perl6 -e  ' "lowered.txt".IO.spurt: "infile.txt".IO.slurp.lc '

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

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

for line in sys.stdin:
    print(line[:-1].lower(), file=sys.stdout)

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

相关问题 更多 >