공백 이외의 항목이 포함된 열을 표시하는 마스크를 만들어 "공백만"인 열을 쉽게 찾을 수 있는 스크립트를 작성 중입니다.
이렇게 하려면 각 줄을 "서로 겹치는" 것으로 인쇄하고 공백을 "오른쪽 화살표"로 수정했습니다. (또 다른 단계는 "마지막 헤더의 시작 부분보다 더 먼 열" 뒤에 표시되는 공백을 무시하는 것입니다. 그러나 여기서는 이것이 주제가 아닙니다.)
<Esc>[C
마지막 단계: 생성/해석에 사용된 모든 \r, \n 및 (= 오른쪽 화살표)를 사용 하지 않고 결과 문자열(내 터미널이 올바르게 표시하는 출력)을 얻는 방법에 문제가 있습니다 .
예:
$ PS2=""
$ Esc=$( printf '\033' )
$ Right=$( printf "${Esc}[C" )
$ ps | head -n 2
PID TTY TIME CMD
12415 pts/1160 00:00:00 bash
$ ps | head -n 2 | LC_ALL=C tr '!-~' '*'
*** *** **** ***
***** ******** ******** ****
$ ps | head -n 2 | LC_ALL=C tr '!-~' '*' | sed -e "s/ /${Right}/g" | while read line; do
printf "%s\r" "$line"
done ; printf '\n'
***** ******** ******** ****
## the line above is what I am looking for:
## a "mask" of each column that at one point had a non-space character displayed in it
$ ( ps | head -n 2 | tr '!-~' '*' | sed -e "s/ /${Right}/g" | while read line; do
printf "%s\r" "$line"
done ; printf '\n'
) | cat -ve
^[[C^[[C***^[[C***^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C****^[[C***^M*****^[[C********^[[C********^[[C****^M$
## but of course, the terminal sees (and outputs) this instead, which contains all the "contructing characters"
변수에서 "내 터미널에 표시된 대로" 문자열을 검색하려면 어떻게 해야 합니까?
***** ******** ******** ****
(전체 내용을 " while read -e Finalstring; do print '[%s]' "$finalstring" ; did 로 출력하려고 시도했지만 FinalString에는 여전히 "사후 터미널 대신 "사전 해석된" 문자열 전체가 포함되어 있습니다. 해석했습니다." )
동일한 질문을 하는 간단한 방법:
# if:
$ printf "aaaa\rbb\rc\n"
# displays:
cbaa
$ var=$( printf "aaaa\rbb\rc\n" ) # $var will be: "aaaa\rbb\rc\n"
# how can I instead have the resulting "displayed string": "cbaa" in $var ?
답변1
아직 터미널 이스케이프가 없는 데이터에 터미널 이스케이프를 추가하여 추가 문제를 생성하는 것 같습니다. 원하는 것이 시각화의 빈 열뿐인 경우 (아시다시피)를 ps
사용하여 모두 비어 있는 열 번호로 인덱싱된 배열을 누적하고 필요한 경우 "*"를 얻을 수 있습니다. awk
예를 들어:
awk '
{ len = length($0)
if(len>max)max = len
for(i=1;i<=len;i++) if(substr($0,i,1)!=" ") col[i] = "*"
}
END{ for(i=1;i<=max;i++) if(col[i])str = str "*"; else str = str " ";
print str
}'
답변2
내가 수년 전에 사용했던 간단한 ansi 파서는 Python 모듈에서 제공하는 것입니다.예상하다. (슬프게도 이 기능은 이제 더 이상 사용되지 않으며 pyte
익숙하지 않은 모듈로 대체되었습니다.)
이 오래된 모듈은 여전히 패키지의 일부로 사용 가능한 것 같습니다. 데이터 스트림을 보내면 ansi 이스케이프 시퀀스를 고려하여 40x80 배열의 적절한 위치에 문자를 씁니다.
다음 예제에서는 위로 스크롤 작업을 연결하고 result
80자의 한 줄 배열을 유지하며 공백이 아닌 문자가 화면에서 위로 스크롤될 때마다 "*"를 배치합니다. 대신 화면 호출은 str()
전체 화면을 위로 스크롤하여 새로 고친 다음 이 배열만 반환합니다. 프로그램에 데이터를 입력하기만 하면 됩니다. 공백이 공백이 아닌 문자 등을 덮어쓸 때 배열 업데이트를 억제할 수도 있으므로 이는 시작일 뿐입니다.
#!/usr/bin/python3
# https://unix.stackexchange.com/q/711733/119298
# extend ANSI by noting which cols get non-whitespace
import sys, re
from pexpect.ANSI import ANSI
class KeepScroll(ANSI):
def __init__(self, r=24,c=80):
ANSI.__init__(self,r,c)
ANSI.Log = None
self.result = [" "] * self.cols
def scroll_up(self):
if self.scroll_row_start==1:
for i, ch in enumerate(self.w[0]):
if ch!=" ": self.result[i] = "*"
ANSI.scroll_up(self)
# scroll up rest of screen
def __str__(self):
for i in range(self.rows): self.scroll_up()
return "".join(self.result)
def parsevt100(data):
scr = KeepScroll()
scr.write(data)
return str(scr)
if __name__ == "__main__":
print(parsevt100(sys.stdin.read()))