如何在Perl中获取终端宽度?

14
我想输出一个进度条,但如何在Perl中获取终端宽度?
最好使用核心的Perl解决方案,因为我没有编译器,只有已经安装好的5.8.2 Perl。

5
您始终可以访问编译器。没有法律规定您必须在同一主机上编译它。 - brian d foy
[讽刺]通常是这样...但不是在这里。因为每个人都知道Java和Perl可以在任何计算机上开发,所以在开发平台和生产环境中不需要具有相同的环境(即架构)...[/讽刺] - Steve Schnepp
1
为什么这么讽刺呢?我给你一个真诚的回答。你的开发和生产系统其实并不重要。你可以交叉编译到任何一个系统上。你来这里是为了寻求帮助,我免费提供了帮助,请不要对此嘲笑不屑。 - brian d foy
@brian:很抱歉,我并不是想对你挖苦,而是针对这里的某些人没有给我访问面向生产架构的编译器的权限(嘿,我知道你很认真,我甚至点了+1)。 - Steve Schnepp
4个回答

33
如果你运行perldoc -q "screen size"命令,Perl附带的常见问题解答文档会给出这个问题的答案。

How do I get the screen size?

If you have Term::ReadKey module installed from CPAN, you can use it to fetch the width and height in characters and in pixels:

use Term::ReadKey;
($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();

This is more portable than the raw "ioctl", but not as illustrative:

require 'sys/ioctl.ph';
die "no TIOCGWINSZ" unless defined &TIOCGWINSZ;
open(TTY, "+</dev/tty") or die "No tty: $!";
unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
    die sprintf "$0: ioctl TIOCGWINSZ (%08x: $!)\n", &TIOCGWINSZ;
}
($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
print "(row,col) = ($row,$col)";
print "  (xpixel,ypixel) = ($xpixel,$ypixel)" if $xpixel || $ypixel;
print "\n";

如果您想要一个纯Perl的解决方案,您可以使用最后一个;如果您想在代码中使用更简单的解决方案,但需要更多的前期设置,请从CPAN安装Term::ReadKey


我们如何运行h2ph,以解决错误信息:Can't locate sys/ioctl.ph in @INC (did you run h2ph?) - Steve Schnepp
@Steve:当您尝试运行h2ph时会发生什么? - Ether
@Ether:我错过了h2ph-d选项。现在它显示ioctl.pl:ioctl TIOCGWINSZ(40007468:系统调用收到一个无效的参数。) - Steve Schnepp
我想指出的是,TIOCGWINSZ在BSD上不起作用,但是“许多”人已经复制了这个“解决方案”,因为它似乎不需要额外的模块。请避免使用它。 - Nei
这在makefile中不起作用。显然,在任何没有控制终端的东西中使用此模块都是一个错误,当然是make在控制终端。太糟糕了 - 我想知道是否有另一种方法让它工作。(编辑:可能使makefile导出COLUMNS和LINES会起作用,但如果尝试tput或stty size会更好)。 - rjh

15

这显然取决于平台,但在Linux上可以直接使用一个非常简单的解决方案:

my $width = `tput cols`;

8
如果你想制作进度条,不必过于纠结细节。使用CPAN上众多的进度条模块之一即可完成。

+1 如果您能提供更高级的答案。很遗憾,Term::ProgressBar 还需要 Term::ReadKey :-( - Steve Schnepp
1
Console::ProgressBar非常基本,但在我看来,它比Term::ProgressBar做得更好。在我的比较中,后者的估计剩余时间(ETA)是我偏好它的唯一原因(仅当您的运行时间相对均匀时)。 - UncleCarl
1
Console::ProgressBar非常基本,但在我看来,它比Term::ProgressBar做得更好。在我的比较中,后者的ETA是我更喜欢它的唯一原因(只有在您的运行时间相对均匀的情况下)。 - undefined

6

虽然不是 Perl 核心的一部分,但了解它仍然很有用。 - Steve Schnepp
1
有一个纯Perl版本。您不需要编译器来安装它。 - Dan
@Dan:哦...那我就去看看吧 :-) - Steve Schnepp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接