Как найти ширину и высоту окна терминала?

В качестве простого примера я хочу написать скрипт CLI, который может печатать = по всей ширине окна терминала.

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

или

#!/usr/bin/env python
print '=' * ???

или

#!/usr/bin/env bash
x=0
while [ $x -lt ??? ]; do echo -n '='; let x=$x+1 done; echo

Ответ 1

  • tput cols указывает количество столбцов.
  • tput lines указывает количество строк.

Ответ 2

В bash переменные среды $LINES и $COLUMNS должны иметь возможность сделать трюк. Он будет автоматически установлен при любом изменении размера терминала. (т.е. сигнал SIGWINCH)

Ответ 3

И там stty, из coreutils

$ stty size
60 120 # <= sample output

Он напечатает количество строк и столбцов или высоту и ширину соответственно.

Затем вы можете использовать cut или awk, чтобы извлечь нужную часть.

Это stty size | cut -d" " -f1 для высоты/линий и stty size | cut -d" " -f2 для ширины/столбцов

Ответ 4

yes = | head -n$(($(tput lines) * $COLUMNS)) | tr -d '\n'

Ответ 5

Чтобы сделать это в среде CLI Windows, лучший способ найти это - использовать команду 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;
}

Надеюсь, это полезно!

ПРИМЕЧАНИЕ. Возвращаемая высота - это количество строк в буфере, а не количество строк, которые видны внутри окна. Какие-нибудь лучшие варианты там?

Ответ 6

В POSIX, в конечном счете, вы хотите вызвать вызов TIOCGWINSZ (Get WINdow SiZe) ioctl(). Для большинства языков для этого должна быть какая-то обертка. Например, в Perl вы можете использовать Term::Size:

use Term::Size qw( chars );

my ( $columns, $rows ) = chars \*STDOUT;

Ответ 7

Как я уже упоминал в ответе лисица, его код не будет работать на неанглийском языке Windows, потому что тогда вывод mode может не содержать подстроки "столбцы" или "строки":

                                          mode command output

Вы можете найти правильную подстроку без поиска текста:

 preg_match('/---+(\n[^|]+?){2}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];

Заметьте, что я даже не беспокоюсь о строках, потому что это ненадежно (и на самом деле их не волнует).

Изменить: Согласно комментариям о Windows 8 (о, вы...), я думаю, что это может быть более надежным:

 preg_match('/CON.*:(\n[^|]+?){3}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];

Протестируйте это, потому что я не тестировал его.

Ответ 8

Вдохновленный ответом @pixelbeat, здесь появилась горизонтальная полоса с помощью tput, небольшого неправильного использования printf padding/fill и tr

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

Ответ 9

В некоторых случаях ваши строки/строки и столбцы не соответствуют фактическому размеру используемого "терминала". Возможно, у вас нет доступных "tput" или "stty".

Вот функция bash, которую вы можете использовать для визуальной проверки размера. Это будет работать до 140 столбцов х 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"
}