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