webentwicklung-frage-antwort-db.com.de

Wie finde ich die Breite und Höhe eines Terminalfensters?

Als einfaches Beispiel möchte ich ein CLI-Skript schreiben, das '=' über die gesamte Breite des Terminalfensters drucken kann.

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

oder

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

oder

#!/usr/bin/env bash
x=0
while [ $x -lt ??? ]; do echo -n '='; let x=$x+1 done; echo
238
too much php
  • tput cols gibt die Anzahl der Spalten an.
  • tput lines gibt die Anzahl der Zeilen an.
451
TonyUser

In bash sollten die Umgebungsvariablen $LINES und $COLUMNS in der Lage sein, den Trick auszuführen. Das wird bei jeder Änderung der Terminalgröße automatisch eingestellt. (d. h. das SIGWINCH Signal)

82
David Dean

Und es gibt stty , aus coreutils

$ stty size
60 120 # <= sample output

Es werden die Anzahl der Zeilen und Spalten bzw. Höhe und Breite gedruckt.

Dann können Sie entweder cut oder awk verwenden, um den gewünschten Teil zu extrahieren.

Das ist stty size | cut -d" " -f1 für die Höhe/Zeilen und stty size | cut -d" " -f2 für die Breite/Spalten

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

Um dies in der Windows-CLI-Umgebung zu tun, kann ich am besten den Modusbefehl verwenden und die Ausgabe analysieren.

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;
}

Ich hoffe es ist nützlich!

NOTE: Die zurückgegebene Höhe gibt die Anzahl der Zeilen im Puffer an, nicht die Anzahl der Zeilen, die innerhalb des Fensters sichtbar sind. Gibt es bessere Möglichkeiten da draußen?

12
lyceus

Unter POSIX möchten Sie letztendlich den Aufruf TIOCGWINSZ (Get WINdow SiZe) ioctl() aufrufen. Die meisten Sprachen sollten dafür eine Art Hülle haben. Zum Beispiel in Perl können Sie Term :: Size verwenden:

use Term::Size qw( chars );

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

Wie ich in der Antwort von lyceus erwähnt habe, wird sein Code auf nicht englischsprachigen Windows-Fenstern fehlschlagen, da dann die Ausgabe von mode nicht die Teilzeichenfolgen "Spalten" oder "Zeilen" enthalten kann:

mode command output

Sie können den richtigen Teilstring finden, ohne nach Text zu suchen:

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

Beachten Sie, dass ich mich nicht mit Linien beschäftige, weil sie unzuverlässig sind (und mir eigentlich egal ist).

Edit: Laut Kommentaren zu Windows 8 (oh du ...) denke ich, dass dies zuverlässiger sein kann:

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

Testen Sie es trotzdem, weil ich es nicht getestet habe.

4
Camilo Martin

Inspiriert durch die Antwort von @ pixelbeat, hier ist ein horizontaler Balken, der durch tput zur Existenz gebracht wurde, ein leichter Missbrauch von printf Abfüllung/Füllung und tr 

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

Es gibt Fälle, in denen Ihre Zeilen/Zeilen und Spalten nicht der tatsächlichen Größe des verwendeten Terminals entsprechen. Möglicherweise haben Sie keinen "Tput" oder "Stty" zur Verfügung.

Hier ist eine Bash-Funktion, mit der Sie die Größe visuell überprüfen können. Dies funktioniert bis zu 140 Spalten x 80 Zeilen. Sie können die Maximalwerte nach Bedarf anpassen.

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"
}
0
pourhaus