Terminal 我如何找到宽度&;终端窗口的高度?

Terminal 我如何找到宽度&;终端窗口的高度?,terminal,Terminal,作为一个简单的示例,我想编写一个CLI脚本,它可以跨整个终端窗口打印= #!/usr/bin/env php <?php echo str_repeat('=', ???); 或 tput cols告诉您列数 t输出行告诉您行数 在bash中,$行和$列环境变量应该能够做到这一点。当终端尺寸发生任何变化时,将自动设置。(即信号)要在Windows CLI环境中执行此操作,我能找到的最佳方法是使用mode命令并解析输出 function getTerminalSizeOnWindows(

作为一个简单的示例,我想编写一个CLI脚本,它可以跨整个终端窗口打印
=

#!/usr/bin/env php
<?php
echo str_repeat('=', ???);

  • tput cols
    告诉您列数
  • t输出行
    告诉您行数

在bash中,
$行
$列
环境变量应该能够做到这一点。当终端尺寸发生任何变化时,将自动设置。(即信号)

要在Windows CLI环境中执行此操作,我能找到的最佳方法是使用mode命令并解析输出

function getTerminalSizeOnWindows() {
  $output = array();
  $size = array('width'=>0,'height'=>0);
  exec('mode',$output);
  foreach($output as $line) {
    $matches = array();
    $w = preg_match('/^\s*columns\:?\s*(\d+)\s*$/i',$line,$matches);
    if($w) {
      $size['width'] = intval($matches[1]);
    } else {
      $h = preg_match('/^\s*lines\:?\s*(\d+)\s*$/i',$line,$matches);
      if($h) {
        $size['height'] = intval($matches[1]);
      }
    }
    if($size['width'] AND $size['height']) {
      break;
    }
  }
  return $size;
}
我希望它有用


注意:返回的高度是缓冲区中的行数,而不是窗口中可见的行数。还有更好的选择吗?

在POSIX上,最终您希望调用
TIOCGWINSZ
(获取窗口大小)
ioctl()
调用。大多数语言都应该有这样的包装器。例如,在Perl中,您可以使用:


正如我在lyceus answer中提到的,他的代码将在非英语语言环境窗口中失败,因为
mode
的输出可能不包含子字符串“columns”或“line”:

您可以在不查找文本的情况下找到正确的子字符串:

 preg_match('/---+(\n[^|]+?){2}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];
preg_match('/--+(\n[^ |]+?){2}(?\d+/'),`mode`,$matches);
$cols=$matches['cols'];
请注意,我甚至不担心线路,因为它不可靠(实际上我并不关心它们)

编辑:根据对Windows 8的评论(哦,你…),我认为这可能更可靠:

 preg_match('/CON.*:(\n[^|]+?){3}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];
preg_match('/CON.*:(\n[^ |]+?){3}(?\d+/”,'mode`,$matches);
$cols=$matches['cols'];
但一定要测试一下,因为我没有测试它。

还有,从

$stty大小

60 120#受@pixelbeat答案的启发,这里有一个水平条,它是由
tput
产生的,对
printf
填充和
tr

printf "%0$(tput cols)d" 0|tr '0' '='

在某些情况下,行/行和列与正在使用的“终端”的实际大小不匹配。可能您没有可用的“tput”或“stty”

下面是一个bash函数,您可以使用它直观地检查大小。这将最多使用140列x 80行。您可以根据需要调整最大值

function term_size
{
    local i=0 digits='' tens_fmt='' tens_args=()
    for i in {80..8}
    do
        echo $i $(( i - 2 ))
    done
    echo "If columns below wrap, LINES is first number in highest line above,"
    echo "If truncated, LINES is second number."
    for i in {1..14}
    do
        digits="${digits}1234567890"
        tens_fmt="${tens_fmt}%10d"
        tens_args=("${tens_args[@]}" $i)
    done
    printf "$tens_fmt\n" "${tens_args[@]}"
    echo "$digits"
}


这不是对问题的直接回答,而是一个很棒的演示脚本。这是一个多么好的例子啊!这些年我怎么会错过了
tr
命令?这是什么语言?它看起来像一个有语法错误的shell脚本。(在shell中,赋值等号周围不能有空格,并且第一个管道似乎不合适。)
yes'='
将输出无限多的'='行,下面的命令组织得足以填充终端。但是,这些环境变量仅对bash可用,对bash内部运行的任何程序都不可用(像perl、python、ruby),除了交互式bash会话之外,这在任何情况下都不起作用(如果运行脚本,它就不再是交互式的)。在脚本中唯一可以使用它的地方是bash中的prompt_命令。实际上,如果设置
checkwinsize
选项,它在非交互式脚本中也可以工作。例如,此非交互式脚本将打印运行它的终端的尺寸:
shopt-s checkwinsize;(:);echo$LINES$COLUMNS
(在等待子shell完成后,
checkwinsize
选项仅初始化变量,这就是为什么我们需要
(:)
语句的原因)
$LINES
$COLUMNS
在发送
SIGWINCH
后更新,实际上是在任何交互式命令执行之后。如果尝试使用
trap SIGWINCH
更新
PS1
,则不能使用
$LINES
$COLUMNS
,它们保留旧值((
仅由bash设置为shell变量。除非导出这些shell变量,否则bash不会将它们设置为环境变量。
echo-e“行\ncols”|tput-S
要同时获取行和列,请参见:
tput
是一个很好的命令,用于读取终端状态、控制光标和文本属性等。方便的别名,例如:
alias dim=“echo$(tput cols)x$(tput行)”
,这可能会导致
80x50
。此问答可能属于unix或超级用户SE站点。@您提供的alias命令在获取shell源代码时会得到评估。您需要对alias命令使用单引号。例如:
alias dim='echo Terminal Dimensions:$(tput cols)columns x$(tput lines)行“
注意这有一个问题:此命令的输出是特定于区域设置的。换句话说,这不会像在另一个Windows区域设置上那样工作。这是我在Windows 7上得到的结果:添加了一个带有解决方案的答案。+1但是!您的方法在Win8中不起作用。我得到多行
--
。@标记,很好,这只是一个问题非常好。谢谢Windows。我就是这样做的:
$mode=`mode`;list($rows,$cols)=数组\u切片(preg\u split('/\n/',substr($mode,strpos($mode,'CON:')),2,2)
。然后我只替换除数字以外的所有内容。@AleksandrMakov我想知道如果有像
CON设备状态:
?这样顺序的语言会发生什么?也许匹配像
CON.*:
这样的东西会更好。@Mark我实际上在问自己那件事。我为什么要这么做?我怀疑,我只是假设了这是出于某种原因,并采用了它,lol。这种样式不能与管道一起使用,建议使用tput样式。tput的问题是,当stty在每个tty中都可用时,tput并不总是可用的。感谢您提供的信息!
stty
不是来自coreutils的。stty是POSIX标准,因此几乎可以在任何地方使用,也可以在定义itely不会有coreutil Coreutils
 preg_match('/---+(\n[^|]+?){2}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];
 preg_match('/CON.*:(\n[^|]+?){3}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];
$ stty size
60 120 # <= sample output
printf "%0$(tput cols)d" 0|tr '0' '='
function term_size
{
    local i=0 digits='' tens_fmt='' tens_args=()
    for i in {80..8}
    do
        echo $i $(( i - 2 ))
    done
    echo "If columns below wrap, LINES is first number in highest line above,"
    echo "If truncated, LINES is second number."
    for i in {1..14}
    do
        digits="${digits}1234567890"
        tens_fmt="${tens_fmt}%10d"
        tens_args=("${tens_args[@]}" $i)
    done
    printf "$tens_fmt\n" "${tens_args[@]}"
    echo "$digits"
}