吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2115|回复: 5
收起左侧

[其他原创] 控制台特殊字符实现光标控制&批处理中的小技术

[复制链接]
luliucheng 发表于 2022-11-25 20:17

前言

上一次涛之雨大佬已经在这篇文章中讲解了彩色字符的打印方法:ANSI转义码[维基(内容已经多了一点了)]但事实上,ANSI转义码的用处不止于此。

ANSI转义码还能做什么

ANSI转义码还能够修改文本样式,控制光标位置。比如,下面这张表列出了一些常用的并且最新版Windows终端支持的用于控制光标的ANSI转义码:(此表摘自前文给出的链接)

代码 名称 作用
CSI n A CUU – 光标上移(Cursor Up) 光标向指定的方向移动n(默认1)格。如果光标已在屏幕边缘,则无效。
CSI n B CUD – 光标下移(Cursor Down) 同上
CSI n C CUF – 光标前移(Cursor Forward) 同上
CSI n D CUB – 光标后移(Cursor Back) 同上
CSI n E CNL – 光标移到下一行(Cursor Next Line) 光标移动到下面第n(默认1)行的开头。
CSI n F CPL – 光标移到上一行(Cursor Previous Line) 光标移动到上面第n(默认1)行的开头。
CSI n G CHA – 光标水平绝对(Cursor Horizontal Absolute) 光标移动到第n(默认1)列。
CSI n;m H CUP – 光标位置(Cursor Position) 光标移动到第n行、第m列。值从1开始,且默认为1(左上角)。例如CSI ;5HCSI 1;5H含义相同;CSI 17;HCSI 17HCSI 17;1H三者含义相同。
CSI n J ED – 擦除显示(Erase in Display) 清除屏幕的部分区域。如果n是0(或缺失),则清除从光标位置到屏幕末尾的部分。如果n是1,则清除从光标位置到屏幕开头的部分。如果n是2,则清除整个屏幕。如果n是3,则清除整个屏幕,并删除回滚缓存区中的所有行。
CSI n K EL – 擦除行(Erase in Line) 清除行内的部分区域。如果n是0(或缺失),清除从光标位置到该行末尾的部分。如果n是1,清除从光标位置到该行开头的部分。如果n是2,清除整行。光标位置不变。
CSI n S SU – 向上滚动(Scroll Up) 整页向上滚动n(默认1)行。新行添加到底部。
CSI n T SD – 向下滚动(Scroll Down) 整页向下滚动n(默认1)行。新行添加到顶部。

还有一些转义码用于控制字体样式:

代码 作用 备注
0 重置/正常 关闭所有属性。
1 粗体/增加强度/高亮
2 弱化(降低强度)
3 斜体
4 下划线
5 闪烁
7 反显 前景色与背景色交换。
8 隐藏
9 划除 加上删除线。
22 正常颜色或强度 不强不弱。
23 非斜体
24 关闭下划线
25 关闭闪烁
27 关闭反显
28 关闭隐藏
29 关闭划除

通过这些转义字符,我们可以制作一个极富艺术性(bushi)的批处理。

批处理中的小技术

要制作这样的批处理,首先要生成ESC字符。可以使用以下代码:

for /f %%a in ('echo prompt $E ^| cmd') do set ESC=%%a

然后在代码中可以使用%ESC%表示ESC字符。
批处理中还需要生成随机数,我使用了类似以下的命令:

set /a randout=%random%*随机数的最大值/32767

为什么这样写而不是直接取%random%的余数呢?因为直接取余得到不同数的概率不相等,这与C/C++中直接rand()%n存在的问题是一样的。
另外,为了调用方便,适当使用函数/子程序也能提高编程效率。怎么写子程序?很简单:

echo 调用子程序:
call :name
REM 主程序到此结束,批处理退出:
exit /B

REM 下面是子程序部分
:name
REM name是一个标签,可以标注代码中的跳转点,
REM 也相当于子程序的起点,你可以把它换成你要的名字
echo Hello!
exit /B
REM 上一行指令相当于return,批处理没有子程序结束标记,
REM 必须用exit /B退回主程序。

程序中还使用set /p显示提示信息不换行的特性实现了文本输出不换行:

<nul set /p _dev_stdout=输出文本

批处理源码

注意:多数文本编辑器默认以UTF-8编码保存文件,请在保存批处理时将其以ANSI编码保存!!!

终端的上半部分随机填充方块是使用光标位置控制序列实现的,最底下的一行文本是使用字体样式控制序列实现的。

@echo off

REM 生成ESC字符
for /f %%a in ('echo prompt $E ^| cmd') do set ESC=%%a

set cnt=100
:main
set out=%ESC%[
call :randposY
set out=%out%%randout%;
call :randposX
set out=%out%%randout%H%ESC%[48;2;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%m  %ESC%[0m
<nul set /p _dev_stdout=%out%

REM 每循环10次显示一次新的底部文本
REM 不加判断文本刷新太快,效果很差
set /a cnt=cnt+1
if %cnt% lss 10 (goto main)

call :randstyle
set out=%ESC%[30;1H%ESC%[%randout%m%ESC%[38;2;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%m%ESC%[48;2;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%m批处理精神污染 
call :randstyle
set out=%out%%ESC%[%randout%m%ESC%[38;2;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%m%ESC%[48;2;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%;
call :randcolor
set out=%out%%randout%mBy 吾爱破解论坛 luliucheng%ESC%[0m
<nul set /p _dev_stdout=%out%
set cnt=0
goto main

REM 各种子程序
:randposX
set /a randout=%random%*60/32767*2
exit /B

:randposY
set /a randout=%random%*30/32767
exit /B

:randcolor
set /a randout=%random%/128
exit /B

:randstyle
set randsource=123479
set /a randout=%random%*6/32767
setlocal ENABLEDELAYEDEXPANSION
set randout=!randsource:~%randout%,1!
endlocal
exit /B

免费评分

参与人数 1吾爱币 +7 热心值 +1 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

semiuel 发表于 2022-11-25 21:00
win7 64位,运行后输出内容没有转义
Wapj_Wolf 发表于 2022-11-26 08:50
yuzzuo 发表于 2022-11-26 18:39
 楼主| luliucheng 发表于 2022-11-26 20:11
semiuel 发表于 2022-11-25 21:00
win7 64位,运行后输出内容没有转义

是的,转义序列需要win10系统才能支持。
eaglexiong 发表于 2022-12-2 11:25
学习编程语言要专业,开发算法会提升很多
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 01:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表