开发者

When opening a file in perl, how can I automatically use STDIN/OUT if the file name is "-"?

开发者 https://www.devze.com 2022-12-25 16:11 出处:网络
I have a perl program that takes input and output file arguments, and I\'d like to support the convention of 开发者_如何学Gousing \"-\" to specify standard input/output. The problem is that I can\'t j

I have a perl program that takes input and output file arguments, and I'd like to support the convention of 开发者_如何学Gousing "-" to specify standard input/output. The problem is that I can't just open the file name, because open(my $input, '<', '-') opens a file called -, not standard input. So I have to do something like this:

my $input_fh;
if ($input_filename eq '-') {
    # Special case: get the stdin handle
    $input_fh = *STDIN{IO};
}
else {
    # Standard case: open the file
    open($input_fh, '<', $input_filename);
}

And similarly for the output file. Is there any way to do this without testing for the special case myself? I know I could hack the ARGV filehandle to do this for input, but that won't work for output.

Edit: I've been informed that the 2-argument form of open actually does the magic I'm looking for. Unfortunately, it also does some creative interpretation in order to separate the filename from the mode in the second argument. I guess the 3-argument form of open is 100% magic-free -- it always opens the exact file you tell it to. I'm asking if I can have a single exception for "-" while still handling every other file name unambiguously.

Should I just stick my code from above into a subroutine/module and stop whining?


Use the two-arguments form instead:

open ($input_fh, "< " . $input_filename);

From man perlfunc:

In the 2-arguments (and 1-argument) form opening "'-'" opens STDIN and opening "'>-'" opens STDOUT.

Note that the < mode is optional in the 2-arguments form, so "< -" is perfectly legal.


I think I found what I'm looking for. There's a nifty module called IO::All that does what I want and more.

For Debian/Ubuntu/similar users, the package is called libio-all-perl. I wanted to make that a clickable link to "apt:libio-all-perl", but apparently only http links are allowed here.


Edit

There's also Iterator::Diamond, which implements the tunable magic that I'm asking for. It's designed for replacing the "diamond" operator <>, but it will probably do what I ask if called with just a single file (presumably with some overhead, but who cares?).

0

精彩评论

暂无评论...
验证码 换一张
取 消