将控制字符应用于字符串 - Python
Apply control characters to a string - Python
我正在尝试将控制字符(例如应该删除前缀字符的 '\x08 \x08')应用于字符串(向后移动,写入 space,向后移动)
例如,当我输入 python 控制台时:
s = "test\x08 \x08"
print s
print repr(s)
我进入我的终端:
tes
'test\x08 \x08'
我正在寻找一个函数,比方说 "function",它将 'apply' 控制字符到我的字符串:
v = function("test\x08 \x08")
sys.stdout.write(v)
sys.stdout.write(repr(v))
所以我得到一个 "clean",无控制字符的字符串:
tes
tes
我知道在终端中,这部分由客户端处理,所以也许有一种方法可以使用核心 unix 函数显示 字符串
echo -e 'test\x08 \x08'
cat file.out # control char are here handled by the client
>> tes
cat -v file.out # which prints the "actual" content of the file
>> test^H ^H
实际上,答案比简单的格式化要复杂一些。
进程发送到终端的每个字符都可以看作是有限状态机 (FSM) 中的一个转换。此 FSM 的状态大致对应于显示的句子和光标位置,但还有许多其他变量,例如终端的尺寸、当前输入的控制序列*、终端模式(例如:VI 模式/经典 BASH 控制台)等
可以在 pexpect source code.
中看到此 FSM 的良好实现
回答我的问题,没有核心 unix "function" 可以将字符串格式化为终端中显示的内容,因为这样的函数特定于呈现进程输出的终端,您将不得不重写一个完整的终端来处理每个可能的字符和控制序列。
不过我们可以自己实现一个简单的。我们需要定义一个具有初始状态的 FSM :
- 显示的字符串:“”(空字符串)
- 光标位置:0
和转换(输入字符):
- 任何alphanumeric/space字符:将光标位置的字符替换为自身(如果有none则添加)并增加光标位置
\x08
十六进制代码:递减光标位置
并将字符串提供给它。
Python解决方案
def decode(input_string):
# Initial state
# String is stored as a list because
# python forbids the modification of
# a string
displayed_string = []
cursor_position = 0
# Loop on our input (transitions sequence)
for character in input_string:
# Alphanumeric transition
if str.isalnum(character) or str.isspace(character):
# Add the character to the string
displayed_string[cursor_position:cursor_position+1] = character
# Move the cursor forward
cursor_position += 1
# Backward transition
elif character == "\x08":
# Move the cursor backward
cursor_position -= 1
else:
print("{} is not handled by this function".format(repr(character)))
# We transform our "list" string back to a real string
return "".join(displayed_string)
还有一个例子
>>> decode("test\x08 \x08")
tes
关于控制序列的注意事项
ANSI 控制序列是一组字符,充当终端(display/cursor/terminal 模式/...)状态的转换。它可以看作是我们 FSM 状态和转换的改进,具有更多的子状态和子转换。
例如:当你在经典的Unix终端(如VT100)中按下UP键时,实际上输入的是控制序列:ESC 0 A
其中ESC
是十六进制代码\x1b
. ESC
进入ESCAPE模式,A后returns进入普通模式
一些进程将此序列解释为垂直光标位置 (VI) 的移动,其他进程将此序列解释为历史记录中的向后移动 (BASH):它完全取决于处理输入的程序。
但是,可以在输出过程中使用相同的序列,但它很可能会在屏幕中向上移动光标:这取决于终端实现。
一个很好的 ANSI 控制序列列表可用 here。
我正在尝试将控制字符(例如应该删除前缀字符的 '\x08 \x08')应用于字符串(向后移动,写入 space,向后移动)
例如,当我输入 python 控制台时:
s = "test\x08 \x08"
print s
print repr(s)
我进入我的终端:
tes
'test\x08 \x08'
我正在寻找一个函数,比方说 "function",它将 'apply' 控制字符到我的字符串:
v = function("test\x08 \x08")
sys.stdout.write(v)
sys.stdout.write(repr(v))
所以我得到一个 "clean",无控制字符的字符串:
tes
tes
我知道在终端中,这部分由客户端处理,所以也许有一种方法可以使用核心 unix 函数显示 字符串
echo -e 'test\x08 \x08'
cat file.out # control char are here handled by the client
>> tes
cat -v file.out # which prints the "actual" content of the file
>> test^H ^H
实际上,答案比简单的格式化要复杂一些。
进程发送到终端的每个字符都可以看作是有限状态机 (FSM) 中的一个转换。此 FSM 的状态大致对应于显示的句子和光标位置,但还有许多其他变量,例如终端的尺寸、当前输入的控制序列*、终端模式(例如:VI 模式/经典 BASH 控制台)等
可以在 pexpect source code.
中看到此 FSM 的良好实现回答我的问题,没有核心 unix "function" 可以将字符串格式化为终端中显示的内容,因为这样的函数特定于呈现进程输出的终端,您将不得不重写一个完整的终端来处理每个可能的字符和控制序列。
不过我们可以自己实现一个简单的。我们需要定义一个具有初始状态的 FSM :
- 显示的字符串:“”(空字符串)
- 光标位置:0
和转换(输入字符):
- 任何alphanumeric/space字符:将光标位置的字符替换为自身(如果有none则添加)并增加光标位置
\x08
十六进制代码:递减光标位置
并将字符串提供给它。
Python解决方案
def decode(input_string):
# Initial state
# String is stored as a list because
# python forbids the modification of
# a string
displayed_string = []
cursor_position = 0
# Loop on our input (transitions sequence)
for character in input_string:
# Alphanumeric transition
if str.isalnum(character) or str.isspace(character):
# Add the character to the string
displayed_string[cursor_position:cursor_position+1] = character
# Move the cursor forward
cursor_position += 1
# Backward transition
elif character == "\x08":
# Move the cursor backward
cursor_position -= 1
else:
print("{} is not handled by this function".format(repr(character)))
# We transform our "list" string back to a real string
return "".join(displayed_string)
还有一个例子
>>> decode("test\x08 \x08")
tes
关于控制序列的注意事项
ANSI 控制序列是一组字符,充当终端(display/cursor/terminal 模式/...)状态的转换。它可以看作是我们 FSM 状态和转换的改进,具有更多的子状态和子转换。
例如:当你在经典的Unix终端(如VT100)中按下UP键时,实际上输入的是控制序列:ESC 0 A
其中ESC
是十六进制代码\x1b
. ESC
进入ESCAPE模式,A后returns进入普通模式
一些进程将此序列解释为垂直光标位置 (VI) 的移动,其他进程将此序列解释为历史记录中的向后移动 (BASH):它完全取决于处理输入的程序。
但是,可以在输出过程中使用相同的序列,但它很可能会在屏幕中向上移动光标:这取决于终端实现。
一个很好的 ANSI 控制序列列表可用 here。