如何从PHP命令行界面获取Linux控制台的$COLUMNS和$ROWS?

28

我正在为PHP创建一个新的CLI库,我想找出它所运行的控制台的宽度/高度。

我尝试过很多方法,比如查看$_ENV,执行("echo $COLUMNS")等,但没有结果,而如果我在Bash命令行中键入echo $COLUMNS或$ROWS,它会很好地显示值。

我需要做些什么才能从PHP访问这个值?

我正在使用像这样的.sh脚本:

#!/usr/bin/php -q
<?php

require_once('lib.commandline.php');


class HelloWorld extends CommandLineApp {

  public function main($args) {

       echo('O, Hai.');

    }

}

更新 最终解决方案:

public function getScreenSize() { 
      preg_match_all("/rows.([0-9]+);.columns.([0-9]+);/", strtolower(exec('stty -a |grep columns')), $output);
      if(sizeof($output) == 3) {
        $this->settings['screen']['width'] = $output[1][0];
        $this->settings['screen']['height'] = $output[2][0];
      }
    }

3
嗯...我意识到已经接近10年了,但你还有那个CLI库吗?在Github上? :-) - MSpreij
@MSpreij 这是他的 GitHub。顺便说一句,我什么也没找到。 - jkoop
7个回答

56

另一个不需要解析的shell选项是tput

$this->settings['screen']['width'] = exec('tput cols')
$this->settings['screen']['height'] = exec('tput lines')

太好了。在查找如何仅从 stty 获取该信息时,我完全忘记了 tput - Joe Koberg
太棒了!非常有用的温馨提示,关于优雅解决方案的实现。 - Paul T. Rawkeen
1
如果您在Windows上安装了Git,此解决方案甚至也可以工作。另一种选择是解析“mode con /status”。 - David Refoua
作为一条注释:tput 返回的值在调整窗口大小后不会更新,但 stty 会更新。 - pmiguelpinto
@pmiguelpinto:怎么了?对我来说似乎可以工作。 - Dennis Williamson

6
使用 PHP ncurses_getmaxyx 函数。
ncurses_getmaxyx (STDSCR, $Height, $Width)

之前:

http://php.net/manual/en/function.getenv.php

$cols = getenv('COLUMNS');
$rows = getenv('ROWS');

“正确”的方法可能是调用 TIOCGSIZE ioctl 以获得内核对窗口大小的理解,或调用命令 stty -a 并解析结果以获取 rowscolumns


只是想说,在 Mac OS X 的 Terminal.app 中没有设置 COLUMNS 和 ROWS。我也遇到了这些不一致的问题(例如,在 irb 中它们有效,但在执行 Ruby 脚本时却无效等)。 - Jeffrey Aylesworth
如果在程序运行时调整终端大小,环境变量也不会被更新。 - ephemient
Getenv确实不起作用,$_ENV也是如此。但感谢您提供stty -a的提示,我会解析它的 :) - SchizoDuckie
我喜欢我的当前解决方案的可移植性 :) 并非所有的 PHP 环境都有 ncurses,因此我希望它尽可能地简洁。 - SchizoDuckie
1
假设您是这个问题的获胜者,而且您当前的顶级建议是一个“实验性”的函数(这是他们的大写字母,不是我的),您能否花点时间整合这里的各种方法,并展示实际正确的答案。特别是因为您暗示 ioctl 方法是首选方法(但没有说出为什么它是最好的),但您实际上没有展示如何执行此操作。注意:与其抱怨这个问题,不如等待六个月,写一个非常好的答案。记得感谢 Joe 写了一个答案,而不是只抱怨。 - ftrotter
答案中的链接已失效。 - Ismael Miguel

4
我不知道为什么有人需要使用grep来解析stty的输出:它有一个独立的选项可以报告“根据内核的行数和列数”。
一行代码,没有错误处理:
list($rows, $cols) = explode(' ', exec('stty size'));

一行代码,假设在出现问题时两行/列都为0,并抑制任何错误输出:

Original Answer翻译成"最初的回答"

list($rows, $cols) = explode(' ', @exec('stty size 2>/dev/null') ?: '0 0');

3

$COLUMNS$LINES 可能没有被导出到您的程序中。您可以在运行应用程序之前执行 export LINES COLUMNS 命令,或者您可以直接获取这些信息:

$fp=popen("resize", "r");
$b=stream_get_contents($fp);
preg_match("/COLUMNS=([0-9]+)/", $b, $matches);$columns = $matches[1];
preg_match("/LINES=([0-9]+)/", $b, $matches);$rows = $matches[1];
pclose($fp);

2

记录一下,这是我的函数(PHP 7.2及更高版本):

它在Windows和Linux上都可以运行。如果出现错误,它会返回80。

对于一些奇怪或太小的值,它会返回最小值(80)

附注:“mode con”确实会返回行数,但它基于缓冲区而不是屏幕大小。

附注2:奇怪的是,如果我将其作为网站运行,它会返回120(Windows主机)。

   function calculateColSize($min=80) {
       try {
            if (PHP_OS_FAMILY === 'Windows') {
                $a1 = shell_exec('mode con');
                /*
                 * Estado para dispositivo CON:
                 * ----------------------------
                 * Líneas:              9001
                 * Columnas:            85
                 * Ritmo del teclado:   31
                 * Retardo del teclado: 1
                 * Página de códigos:    65001
                 */
                $arr = explode("\n", $a1);
                $col = trim(explode(':', $arr[4])[1]);

            } else {
                $col = exec('tput cols');
                /*
                 * 184
                 */
            }
        } catch (Exception $ex) {
            $col = 80;
        }
    }

1

也许这个链接可能是答案,您可以使用 ANSI 转义码来实现,通过使用 echo 使用特定的转义码序列,特别是“查询设备”,我在另一个链接 这里 中找到了详细的解释。也许使用它可以让您获得屏幕的列和行...


这个答案指向了两个已经失效的链接。此外,这个答案没有解释如何在发送转义序列后获取控制台大小。 - Ismael Miguel

-2

环境变量可以在 $_ENV 超全局变量中找到。

echo $_ENV['ROWS'];

例如。


“我尝试了很多事情,比如挖掘 $_ENV、执行(“echo $COLUMNS”)等等,但都没有结果,”发帖者提到。 - MAChitgarha

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