file - 将 STDIN 保存到 Perl 中的文件?
问题描述
我正在尝试使用 Perl 来:
- 等到至少 1 个字节到达 STDIN
- 读取所有 STDIN 并将其保存为二进制文件(兼容 UTF-8)
我的尝试:
# read STDIN into a string/buffer and save it (maybe this only reads one line):
echo hello | perl -e 'open (fh, ">", "my_filename.txt"); print fh <STDIN>';
# or:
echo hello | perl -e 'open STDIN, ">", "my_filename.txt"'
# ideally be able to specify the filename:
echo hello | perl -e 'open STDIN, ">", $ARGV[0]' my_filename.txt
我不能使用 shell 来执行此操作,echo hello > my_filename.txt
因为 shell 有一个古老的错误/功能,其中所有文件句柄都是同时打开的,而不是基于某些依赖逻辑顺序打开的。所以我的计划是等到有字节在 STDIN 上等待,然后再打开目标文件。
不幸的是,我时间紧迫,没有时间重新学习 Perl 的语法。我认为我出错的地方是我试图在这里将 STDIN 称为一个新变量,而不是实际的输入流。我查看了其他各种缓冲解决方案,但不幸的是它们在某些方面都不够用(实际上不工作,不是跨平台的,需要安装额外的可执行文件等)。
如果您直接执行重定向或通过循环块以减少内存使用量,则会获得奖励积分。了解如何从文件读取和写入 STDOUT 也会有所帮助。这在 awk 之类的东西中也是可能的,但请注意,我正在避免使用 sed,因为 GNU sed 和 BSD sed 之间的另一种古老的语法选择很差,这通常会阻止在两个平台上使用单个命令而不进行调整。所以 Perl 似乎是要走的路。
解决方案
我不能确定,但我认为你想做类似的事情
cat foo | some_operation > foo
如果是这样,简单的解决方案是
cat foo | some_operation | sponge foo
但是你直接要求的可以实现如下:
perl -e'
@ARGV or die("usage\n");
my $qfn = shift;
my $line = <>;
open(STDOUT, ">", $qfn)
or die("open $qfn: $!\n");
print $line;
print while <STDIN>;
' file.out
我们可以利用-p
.
perl -pe'
BEGIN {
@ARGV or die("usage\n");
$qfn = shift(@ARGV);
}
if ($. == 1) {
open(STDOUT, ">", $qfn)
or die("open $qfn: $!\n");
}
' file.out
我们可以投进去-s
。
perl -spe'
BEGIN { defined($o) or die("usage\n"); }
if ($. == 1) {
open(STDOUT, ">", $o)
or die("open $o: $!\n");
}
' -- -o=file.out
最后,我们可以摆脱错误检查。
perl -spe'open(STDOUT, ">", $o) if $. == 1' -- -o=file.out
奖励:如果您想从文件而不是 STDIN 中读取,以上所有方法都可以这样做。只需提供要从中读取的文件的名称作为后续参数。您甚至可以提供多个名称。
推荐阅读
- loops - 自动热键:从 ListBox 复制
- java - Eclipse java类在方法注释后插入新行
- javascript - 在 Java 脚本中显示大十进制数
- java - Spring引导端点返回对象,包括2个对象列表
- asp.net-identity - 登录管理器
给出“在此上下文中启动的第二个操作” - python - 无法将 HTML 代码转换为 Python 字符串 KeyError '\n'
- css - 单页多分页
- laravel - @include 在我的导航栏上方创建空行
- c# - Partial view MVC中基于动态下拉列表选择动态改变表数据
- java - Mockmvc put 方法总是返回 204 状态