<p>这里似乎有两个交错的问题,我先解决这个问题。关于如何使Perl和Python都使用具有非常相似行为的调用,请参阅文章的第二部分。在</p>
<p><strong>简短:</strong>它们在<em>如何</em>进行I/O方面有所不同,但都是逐行工作的,Python代码很容易更改,允许与Perl代码相同的命令行调用。另外,两者都可以编写为允许从文件或标准输入流进行输入。在</p>
<hr/>
<p>(1)两个解决方案都是“流式”的,从某种意义上说,它们都是逐行处理输入。Perl代码从<code>STDIN</code>读取数据,而Python代码从一个文件中获取数据,但它们每次都得到一行。从这个意义上说,对于大文件来说,它们的效率相当。在</p>
<p>在Python中逐行读写文件的标准方法是</p>
<pre><code>with open('infile', 'r') as fin, open('outfile', 'w') as fout:
fout.write(fin.read().lower())
</code></pre>
<p>例如,请参见<a href="https://stackoverflow.com/questions/16669428/process-very-large-20gb-text-file-line-by-line">processing a very large file</a>和{a2}上的这些SO帖子。对于逐行处理来说,您读取文件的方式似乎是惯用的方式,请参见例如在<a href="https://stackoverflow.com/questions/8009882/how-to-read-large-file-line-by-line-in-python">reading large-file line-by-line</a>、在<a href="https://stackoverflow.com/questions/18343504/preferred-file-line-by-line-read-idiom-in-python">idiomatic line-by-line reading</a>上发布以及在{a5}上发布另一篇文章。在</p>
<p>将first open here更改为<code>io.open</code>,以直接从命令行中获取第一个参数作为文件名,并根据需要添加模式。在</p>
<p>(2)您显示的带有输入和输出重定向的命令行是一个shell特性</p>
^{pr2}$
<p><code>program</code>通过标准输入流(文件描述符0)馈送行。它们由shell通过其<code><</code><em>重定向</em>从文件<code>input</code>提供。从<a href="https://www.gnu.org/software/bash/manual/html_node/Redirections.html" rel="nofollow noreferrer">gnu bash manual</a>(见3.6.1),其中“<em>word</em>”代表我们的“<em>输入</em>”</p>
<blockquote>
<p>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. </p>
</blockquote>
<p>任何一个程序都可以这样做,即充当一个<em>过滤器</em>。对于Python,可以使用</p>
<pre><code>import sys
for line in sys.stdin:
print line.lower()
</code></pre>
<p>例如,请参阅<a href="https://stackoverflow.com/questions/1589994/how-do-i-write-a-unix-filter-in-python">writing filters</a>上的帖子。现在您可以在shell中将其作为<code>script.py < input</code>调用。在</p>
<p>将代码<code>print</code>转换为标准输出,然后shell可以使用<code>></code>将其重定向。然后得到与Perl脚本相同的调用。在</p>
<p>我认为标准输出重定向<code>></code>在这两种情况下都是明确的。在</p>
<hr/>
<p>最后,您可以通过这种方式使二者具有几乎相同的行为,并允许任何一种调用。在</p>
<p>在Perl中,有以下习惯用法</p>
<pre><code>while (my $line = <>) {
# process $line
}
</code></pre>
<p><em>diamond运算符</em><code><></code>要么从命令行提交的所有文件中逐行获取(这些文件位于<code>@ARGV</code>),要么从<code>STDIN</code>获取行(如果数据以某种方式通过管道传输到脚本中)。从<a href="http://perldoc.perl.org/perlop.html#I%2fO-Operators" rel="nofollow noreferrer">I/O Operators in perlop</a></p>
<blockquote>
<p>The null filehandle <code><></code> 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 <code><></code> comes either from standard input, or from each file listed on the command line. Here's how it works: the first time <code><></code> is evaluated, the <code>@ARGV</code> array is checked, and if it is empty, <code>$ARGV[0]</code> is set to <code>"-"</code> , which when opened gives you standard input. The <code>@ARGV</code> array is then processed as a list of filenames.</p>
</blockquote>
<p>在Python中,通过</p>
<pre><code>import fileinput
for line in fileinput.input():
# process line
</code></pre>
<p>这还将遍历<code>sys.argv</code>中命名的文件行,如果列表为空,则默认为<code>sys.stdin</code>。来自<a href="https://docs.python.org/2/library/fileinput.html" rel="nofollow noreferrer">fileinput</a>文档</p>
<blockquote>
<p>This iterates over the lines of all files listed in <code>sys.argv[1:]</code>, defaulting to <code>sys.stdin</code> if the list is empty. If a filename is <code>'-'</code>, it is also replaced by <code>sys.stdin</code>. To specify an alternative list of filenames, pass it as the first argument to <code>input()</code>. A single file name is also allowed.</p>
</blockquote>
<p>在这两种情况下,如果有命令行参数而不是文件名,则需要做更多的工作。在</p>
<p>有了它,您就可以以任何一种方式使用Perl和Python脚本</p>
<pre><code>lowercase < input > output
lowercase input > output
</code></pre>
<p>或者,在这个问题上,作为<code>cat input | lowercase > output</code>。在</p>
<hr/>
<p>这里的所有方法逐行读取输入和写入输出。解释器、系统和shell的重定向可以进一步优化(缓冲)这一点。可以将其改为以更小的块读和/或写,但这将是非常低效的,并且会显著地减慢程序的速度。在</p>