如何在控制台应用程序(Linux)中删除已打印的字符?

16

我正在创建一个需要进度条的小型控制台应用程序。像这样...

Conversion: 175/348 Seconds   |==========          |  50%

我的问题是,如何删除已经打印到控制台的字符?当我达到51%时,我需要从控制台中删除此行并插入一行新的。在我的当前解决方案中,会发生以下情况...

Conversion: 175/348 Seconds   |==========          |  50%
Conversion: 179/348 Seconds   |==========          |  52%
Conversion: 183/348 Seconds   |==========          |  54%
Conversion: 187/348 Seconds   |===========         |  56%

我使用的代码是...

print "Conversion: $converted_seconds/$total_time Seconds   $progress_bar  $converted_percentage%\n";

我正在使用PHP在Linux上进行此操作(仅我使用该应用程序-因此请原谅语言选择)。因此,解决方案应在Linux平台上运行-但如果您有跨平台的解决方案,那将更可取。


希望这个例子能对你有所帮助。 PHP示例 - 在控制台中删除行 - BlackHammer
6个回答

19

我认为您不需要为语言选择道歉。PHP是编写控制台应用程序的优秀语言。

试试这个:

<?php
for( $i=0;$i<10;$i++){
  print "$i \r";
  sleep(1);
}
?>

"\r"会覆盖行并输入新的文本。如果要换行,只需使用"\n"即可,但我猜你已经知道了这一点。

希望这有所帮助!我知道这在Linux中有效,但我不知道它是否适用于Windows或其他操作系统。


此外,许多愚蠢的终端(或终端仿真器,或脑残帧缓冲模式)会因此而感到困惑,各种SSH客户端也是如此。一个字面上的退格符'\b'是最安全的选择。 - Tim Post
我完全忘记了你可以在shell上这样做。 - David
哇!我要试试这个。会加一些颜色看看它是否有效。 - Viet
@GnomeCubed PHP 永远不应该被使用。 - Nick Sotiros

9

要删除先前打印的字符,您有三个选项:

  • echo chr(8) . " "; 回显退格符,并将光标向后移动一个位置,然后空格覆盖该字符。您可以多次使用 chr(8) 来向后移动多个字符。

  • echo "\r"; 将光标返回到当前行的开头。现在您可以用新文本替换该行。

  • 第三个选项是使用 ANSI 转义码设置光标位置的行和列,然后打印替换字符。它可能无法在所有终端上运行:

  function movecursor($line, $column){
      echo "\033[{$line};{$column}H";
  }

8

\r 可以解决这个问题。

为了以后参考,\b 在Linux中的PHP中不起作用。我很好奇 - 所以我在其他语言中进行了一些实验(我在Linux中进行了此操作 - 我不知道在Windows / Mac中结果是否相同)...

\b 适用于...

  • Perl
  • Ruby
  • Tcl - 代码为 puts -nonewline "Hello\b"

\b 不适用于

  • PHP - 代码 print "Hello\b"; 打印出 Hello\b
  • Python - 代码 print "Hello\b" 打印出 Hello<new line>。使用 print "Hello\b",也得到相同的结果

Python中的print语句会自动添加换行符“\n”。如果您想在同一行上输出内容,请使用sys.stdout.write。 - Matus
退格字符当然还存在!只是在字符串文字中无法使用转义。尝试使用 chr(8) - Luna

4

我不确定在Linux中是否相同,但在Windows控制台应用程序中,您可以打印\r,光标将返回到该行的左侧第一个位置,从而使您可以覆盖右侧的所有字符。

您可以使用\b向后移动单个字符,但由于您将要更新进度条,因此与打印\b多次相比,\r更简单易用。


2

这似乎是一个相当古老的话题,但我会提出我的5个意见。

for ($i; $i<_POSITION_; $i--) {
   echo "\010"; //issue backspace 
}

我在一段时间前在互联网上发现了这篇文章,不幸的是我不记得它的来源。因此,所有的功劳归原作者所有。


0

要删除先前打印的字符,我在其后面打印一个退格符号:

print "a" print "\b"

将打印空白(实际上它会先打印然后是一个退格符号,但你可能不会注意到它)。


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