2015-06-01 11 views
5

Tôi muốn tạo một tệp bao gồm các ký tự không thể in được để chỉ bao gồm các ký tự có thể in. Tôi nghĩ rằng vấn đề này có liên quan đến ACSCII control action, nhưng tôi không thể tìm thấy một giải pháp để làm điều đó và cũng không thể hiểu ý nghĩa của .[16D (ký tự hành động điều khiển ASCII ??) trong tệp sau.Làm cách nào để chỉ lọc các ký tự có thể in trong một tệp trên Bash (linux) hoặc Python?

hexdump đầu vào FILE:

00000000: 4845 4c4c 4f20 5448 4953 2049 5320 5448 HELLO THIS IS TH 
00000010: 4520 5445 5354 1b5b 3136 4420 2020 2020 E TEST.[16D 
00000020: 2020 2020 2020 2020 2020 201b 5b31 3644   .[16D 
00000030: 2020 

Khi tôi cat ed mà nộp vào bash, tôi chỉ nhận được: "HELLO". Tôi nghĩ rằng điều này là do mặc định cat diễn giải hành động kiểm soát ASCII, hai số .[16D s.

Tại sao hai .[16D chuỗi làm cat FILE chỉ để in "HELLO" ?, và ... làm thế nào tôi có thể làm cho tập tin đó chỉ bao gồm các ký tự in, ví dụ: "HELLO"?

+0

bạn đã thử string.printable? – therealprashant

+0

Tôi tự hỏi tại sao thẻ python ... – 0xc0de

+0

Trên hầu hết các hệ thống * nix, và chắc chắn trên bất kỳ hệ thống GNU nào, cần có lệnh [strings] (http://linux.die.net/man/1/strings) . –

Trả lời

2

Các hexdump cho thấy dấu chấm trong .[16D thực sự là một nhân vật chạy thoát, \x1b.
Esc[nDANSI escape code để xóa n ký tự. Vì vậy, Esc[16D yêu cầu thiết bị đầu cuối xóa 16 ký tự, giải thích đầu ra cat.

Có nhiều cách khác nhau để xóa mã thoát ANSI khỏi một tệp, bằng cách sử dụng lệnh Bash (ví dụ: sử dụng sed, như trong câu trả lời của Anubhava) hoặc Python. Tuy nhiên, trong trường hợp như thế này, tốt hơn là chạy tệp thông qua trình giả lập thiết bị đầu cuối để giải thích bất kỳ chuỗi điều khiển chỉnh sửa hiện có nào trong tệp, do đó bạn sẽ nhận được kết quả tác giả của tệp dự định sau khi áp dụng các chuỗi chỉnh sửa đó. Quay lại đầu trang

Một cách để làm điều đó trong Python là sử dụng pyte, một mô-đun Python thực hiện một trình mô phỏng thiết bị đầu cuối tương thích VTXXX đơn giản. Bạn có thể dễ dàng cài đặt nó bằng cách sử dụng pip và đây là tài liệu của nó trên readthedocs.

Đây là một chương trình demo đơn giản diễn giải dữ liệu được đưa ra trong câu hỏi. Nó được viết cho Python 2, nhưng thật dễ dàng để thích nghi với Python 3. pyte là nhận thức Unicode và lớp Stream chuẩn của nó mong đợi các chuỗi Unicode, nhưng ví dụ này sử dụng ByteStream, vì vậy tôi có thể chuyển nó thành một chuỗi byte đơn giản.

#!/usr/bin/env python 

''' pyte VTxxx terminal emulator demo 

    Interpret a byte string containing text and ANSI/VTxxx control sequences 

    Code adapted from the demo script in the pyte tutorial at 
    http://pyte.readthedocs.org/en/latest/tutorial.html#tutorial 

    Posted to http://stackoverflow.com/a/30571342/4014959 

    Written by PM 2Ring 2015.06.02 
''' 

import pyte 


#hex dump of data 
#00000000 48 45 4c 4c 4f 20 54 48 49 53 20 49 53 20 54 48 |HELLO THIS IS TH| 
#00000010 45 20 54 45 53 54 1b 5b 31 36 44 20 20 20 20 20 |E TEST.[16D  | 
#00000020 20 20 20 20 20 20 20 20 20 20 20 1b 5b 31 36 44 |   .[16D| 
#00000030 20 20            | | 

data = 'HELLO THIS IS THE TEST\x1b[16D    \x1b[16D ' 

#Create a default sized screen that tracks changed lines 
screen = pyte.DiffScreen(80, 24) 
screen.dirty.clear() 
stream = pyte.ByteStream() 
stream.attach(screen) 
stream.feed(data) 

#Get index of last line containing text 
last = max(screen.dirty) 

#Gather lines, stripping trailing whitespace 
lines = [screen.display[i].rstrip() for i in range(last + 1)] 

print '\n'.join(lines) 

đầu ra

HELLO 

hex bãi chứa của đầu ra

00000000 48 45 4c 4c 4f 0a         |HELLO.| 
+0

Cảm ơn bạn đã gắn thẻ. Nhưng cat FILE thành một tập tin khác chỉ là một bản sao của FILE, nó cũng bao gồm các ký tự không in được. Tôi đã thử điều đó ... Bạn có giải pháp khác không? .. – freddy

+0

Xin lỗi @freddy. Tôi nên nhận ra rằng 'mèo' sẽ không thực sự xóa sạch những chuỗi điều khiển đó. Tôi hiện đang cố gắng tìm _something_ có thể thực hiện công việc đó, nhưng tôi có thể không tìm ra giải pháp tối nay. –

+0

@freddy: FWIW, đơn giản là loại bỏ bất kỳ chuỗi ANSI nào như 'ESC [nD' không quá khó, mà trong ví dụ trong OP của bạn sẽ cho bạn' HELLO NÀY LÀ TEST'. Bạn có muốn điều đó, hoặc bạn muốn đồng bằng 'HELLO'? –

1

Bạn có thể thử sed lệnh này để loại bỏ tất cả các ký tự không thể in từ một tập tin:

sed -i.bak 's/[^[:print:]]//g' file 
+2

Điều này là đúng, nhưng hãy cẩn thận rằng những gì có thể in được và những gì không phụ thuộc vào cài đặt ngôn ngữ. – lcd047

+0

Đúng vậy, điều đó phụ thuộc vào cài đặt ngôn ngữ. – anubhava

0

giải pháp Minimalistic nói đến cái tâm của tôi là

import string 
printable_string = filter(lambda x: x in string.printable, your_string) 
## TODO: substitute your string in the place of "your_string" 

Nếu vẫn điều này không giúp sau đó thử cũng bao gồm uni-mã cụ thể [curses.ascii]

0

Xem string mô-đun được xây dựng trong.

import string 
printable_str = filter(string.printable, string) 
Các vấn đề liên quan