[英]Run a perl script with Python on multiple files at once in a folder
这是我目前的 perl 脚本:
#!/usr/bin/perl
use open qw/:std :utf8/;
use strict;
use warnings;
if (defined $ARGV[0]){
my $filename = $ARGV[0];
my %count;
open (my $fh, $filename) or die "Can't open '$filename' $!";
while (<$fh>)
{
$count{ lc $1 }++ while /(\w+)/g;
}
close $fh;
my $array = 0;
foreach my $word ( sort { $count{$b} <=> $count{$a} } keys %count)
{
print "$count{$word} $word\n" if $array++ < 10;
}
}else{
print "Please enter the name of the file: ";
my $filename = ($_ = <STDIN>);
my %count;
open (my $fh, $filename) or die "Can't open '$filename' $!";
while (<$fh>)
{
$count{ lc $1 }++ while /(\w+)/g;
}
close $fh;
my $array = 0;
foreach my $word ( sort { $count{$b} <=> $count{$a} } keys %count)
{
print "$count{$word} $word\n" if $array++ < 10;
}
}
这是我目前的 Python 脚本:
#!/usr/bin/env python3
import os
perlscript = "perl " + " perlscript.pl " + " /home/user/Desktop/data/*.txt " + " >> " + "/home/user/Desktop/results/output.txt"
os.system(perlscript)
问题:当数据文件夹中有多个 txt 文件时,脚本仅在一个文件上运行而忽略所有其他 txt 文件。 有没有办法一次在所有 txt 文件上运行 perlscript?
另一个问题:我还尝试在执行后使用 os.remove 删除 txt 文件,但在 perlscript 有机会执行之前它们已被删除。
有任何想法吗? :)
Perl 脚本处理一个文件。 此外,通过os.system
传递给 shell 的字符串不会像*
shell glob 那样扩展为带有文件列表的有效命令。
相反,使用os.listdir
或glob.glob
或os.walk
在 Python 中构建文件列表。 然后遍历列表并在每个文件上调用 Perl 脚本,如果它必须一次只处理一个文件。 或者,修改 Perl 脚本以处理多个文件并使用整个列表运行一次。
保留当前的 Perl 脚本并在每个文件上运行它
import os
data_path = "/home/user/Desktop/data/"
output_path = "/home/user/Desktop/result/"
for file in os.listdir(data_path):
if not file.endswith(".txt"):
continue
print("Processing " + file) # better use subprocess
run_perlscript = "perl " + " perlscript.pl " + \
data_path + file + " >> " + output_path + "output.txt"
os.system(run_perlscript)
需要重写 Perl 脚本以消除不需要的重复代码。
但是,最好使用subprocess模块来运行和管理外部命令。 即使在os.system文档本身中也建议这样做。 例如
import subprocess
with open(output_path + "output.txt", "a") as fout:
for file in os.listdir(path):
if not file.endswith(".txt"):
continue
subprocess.run(["perl", "script.pl", data_path + file], stdout=fout)
在问题的>>
重定向之后以追加模式 ( "a"
) 打开文件的位置。
推荐的subprocess.run从 python 3.5 开始可用; 否则使用Popen 。
另一个可以说是“正确”的选项是调整 Perl 脚本,以便它可以处理多个文件。 然后你只需要运行一次,整个文件列表。
use strict;
use warnings;
use feature 'say';
use open ':std', ':encoding(UTF-8)';
foreach my $filename (@ARGV) {
say "Processing $filename";
my %count;
open my $fh, '<', $filename or do {
warn "Can't open '$filename': $!";
next;
};
while (<$fh>) {
$count{ lc $1 }++ while /(\w+)/g;
}
close $fh;
my $prn_cnt = 0;
foreach my $word ( sort { $count{$b} <=> $count{$a} } keys %count) {
print "$count{$word} $word\n" if $prn_cnt++ < 10;
}
}
这会在无法打开的文件上打印警告并跳到下一个。 如果您希望脚本退出任何意外的文件替换or do { ... };
用原来的die
。
然后,现在以glob.glob为例
import subprocess
data_path = "/home/user/Desktop/data/"
output_path = "/home/user/Desktop/result/"
files = glob.glob(data_path + "*.txt")
with open(output_path + "output.txt", "a") as fout:
subprocess.run(["perl", "script.pl", files], stdout=fout)
由于这将整个列表作为命令参数传递,因此它假定没有(高)数千个文件,以超过管道或命令行的某些长度限制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.