Tôi không hiểu HAI điều.
(1) Đó là mã của bạn, dưới sự kiểm soát của bạn. Bạn muốn thêm chuỗi thoát vào dữ liệu của bạn và sau đó tách chúng ra một lần nữa để bạn có thể tính toán độ dài của dữ liệu của bạn ?? Dường như đơn giản hơn để tính toán phần đệm trước khi thêm chuỗi thoát. Tôi đang thiếu gì?
Giả sử không có trình tự thoát nào thay đổi vị trí con trỏ. Nếu có, câu trả lời hiện được chấp nhận sẽ không hoạt động.Hãy giả sử rằng bạn có dữ liệu chuỗi cho mỗi cột (trước khi thêm chuỗi thoát) trong danh sách có tên string_data
và độ rộng cột được xác định trước nằm trong danh sách có tên là width
. Hãy thử một cái gì đó như thế này:
temp = []
for colx, text in enumerate(string_data):
npad = width[colx] - len(text) # calculate padding size
assert npad >= 0
enhanced = fancy_text(text, colx, etc, whatever) # add escape sequences
temp.append(enhanced + " " * npad)
sys.stdout.write("".join(temp))
Cập nhật sau khi bình luận OP của "" "Lý do tôi muốn lột chúng ra và tính toán chiều dài sau chuỗi chứa mã màu là bởi vì tất cả các dữ liệu được xây dựng theo chương trình. Tôi có một loạt các phương pháp colorize và tôi đang xây dựng dữ liệu như thế này: str = "% s /% s /% s"% (GREEN (dữ liệu 1), BLUE (dữ liệu 2), RED (data3)) khó khăn để tô màu văn bản sau khi thực tế. "" "
Nếu dữ liệu được tạo thành từng phần với định dạng riêng, bạn vẫn có thể tính toán độ dài và pad được hiển thị nếu thích hợp. Dưới đây là một chức năng mà nào đó cho nội dung một tế bào của:
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(40, 48)
BOLD = 1
def render_and_pad(reqd_width, components, sep="/"):
temp = []
actual_width = 0
for fmt_code, text in components:
actual_width += len(text)
strg = "\x1b[%dm%s\x1b[m" % (fmt_code, text)
temp.append(strg)
if temp:
actual_width += len(temp) - 1
npad = reqd_width - actual_width
assert npad >= 0
return sep.join(temp) + " " * npad
print repr(
render_and_pad(20, zip([BOLD, GREEN, YELLOW], ["foo", "bar", "zot"]))
)
Nếu bạn nghĩ rằng cuộc gọi đang quá tải bởi dấu chấm câu, bạn có thể làm một cái gì đó như:
BOLD = lambda s: (1, s)
BLACK = lambda s: (40, s)
# etc
def render_and_pad(reqd_width, sep, *components):
# etc
x = render_and_pad(20, '/', BOLD(data1), GREEN(data2), YELLOW(data3))
(2) Tôi không hiểu tại sao bạn không muốn sử dụng bộ biểu thức chính quy được cung cấp kèm theo Python. Không "hackery" (đối với bất kỳ ý nghĩa có thể của "hackery" mà tôi biết) có liên quan đến:
>>> import re
>>> test = "1\x1b[a2\x1b[42b3\x1b[98;99c4\x1b[77;66;55d5"
>>> expected = "12345"
>>> # regex = re.compile(r"\x1b\[[;\d]*[A-Za-z]")
... regex = re.compile(r"""
... \x1b # literal ESC
... \[ # literal [
... [;\d]* # zero or more digits or semicolons
... [A-Za-z] # a letter
... """, re.VERBOSE)
>>> print regex.findall(test)
['\x1b[a', '\x1b[42b', '\x1b[98;99c', '\x1b[77;66;55d']
>>> actual = regex.sub("", test)
>>> print repr(actual)
'12345'
>>> assert actual == expected
>>>
Cập nhật sau khi bình luận OP của "" "Tôi vẫn thích câu trả lời của Paul vì nó ngắn gọn hơn"" "
Cụ thể hơn là gì? Không phải giải pháp regex đủ ngắn gọn cho bạn:
# === setup ===
import re
strip_ANSI_escape_sequences_sub = re.compile(r"""
\x1b # literal ESC
\[ # literal [
[;\d]* # zero or more digits or semicolons
[A-Za-z] # a letter
""", re.VERBOSE).sub
def strip_ANSI_escape_sequences(s):
return strip_ANSI_escape_sequences_sub("", s)
# === usage ===
raw_data = strip_ANSI_escape_sequences(formatted_data)
??
[Trên đang điều chỉnh sau khi @Nick Perkins chỉ ra rằng nó đã không làm việc]
Đây thực sự là "ANSI" mã màu, không phải "ASCII", như sẽ được hiển thị trên thiết bị đầu cuối màu ANSI hoặc trên PC bằng trình điều khiển ANSI.SYS. – PaulMcG