Bash에서 TAB으로 구분된 문자열을 인쇄하는 방법은 무엇입니까?

Bash에서 TAB으로 구분된 문자열을 인쇄하는 방법은 무엇입니까?

탭으로 구분된 두 개의 문자열을 인쇄하려고 합니다. 나는 시도했다:

echo -e 'foo\tbar'
printf '%s\t%s\n' foo bar

둘 다 인쇄:

foo     bar

둘 사이의 공백은 실제로 5개의 공백입니다(Putty의 마우스 선택 출력 기준).

또한 Ctrl+V를 사용하고 명령을 입력하는 동안 Tab 키를 눌러도 동일한 결과가 나왔습니다.

출력을 선택하고 탭을 사용하여 다른 위치에 복사할 수 있도록 강제로 탭으로 인쇄하는 올바른 방법은 무엇입니까?

두 번째 질문: Bash가 탭을 공백으로 확장하는 이유는 무엇입니까?

고쳐 쓰다:분명히 이것은 Putty 문제입니다. https://superuser.com/questions/656838/how-to-make-putty-display-tabs-within-a-file-instead-of-chang-them-to-spaces

답변1

둘 사이의 공간은 실제로는 5칸이다.

아니요, 그렇지 않습니다. echo또는 의 출력에는 없습니다 printf.

$ echo -e 'foo\tbar' | od -c
0000000   f   o   o  \t   b   a   r  \n
0000010

출력을 선택하고 탭을 사용하여 다른 위치에 복사할 수 있도록 강제로 탭으로 인쇄하는 올바른 방법은 무엇입니까?

이것은 다른 질문입니다. 이는 셸과는 아무 관련이 없지만 출력의 탭 문자를 공백으로 변환하는 터미널 에뮬레이터와 관련이 있습니다. 많은(전부는 아니지만) 사람들이 이렇게 합니다.

탭이 있는 출력을 파일로 리디렉션하고 거기에서 복사하거나 unexpand출력에서 ​​공백을 탭으로 변환하는 것이 더 쉬울 수 있습니다. (공백이 탭으로 시작하고 가능하면 모두 탭으로 변환한다는 사실도 모르지만) 이는 물론 출력으로 수행해야 하는 작업에 따라 다릅니다.

답변2

ilkkachu가 말했듯이 이것은 bash의 문제가 아니라 출력에서 ​​탭을 공백으로 변환하는 터미널 에뮬레이터의 문제입니다.

다른 터미널을 확인하면 putty, xterm 및 konsole은 탭을 공백으로 변환하지만 urxvt 및 gnome-terminal은 그렇지 않습니다. 따라서 또 다른 해결책은 터미널을 전환하는 것입니다.

답변3

에서는 printf '%s\t%s\n' foo barprintf출력합니다 foo<TAB>bar<LF>.

f, o, bar단일 각도 그래픽 문자입니다.

이러한 문자를 수신한 후 터미널은 해당 문자를 표시하고 커서가 화면의 오른쪽 가장자리(원래 텔레타이프 기계의 용지)에 도달하지 않는 한 오른쪽으로 한 열 이동합니다. 이 경우 라인을 입력할 수 있습니다. 터미널과 구성 방식에 따라 화면 왼쪽 가장자리로 돌아가거나(개행) 문자를 삭제합니다.

<Tab>그리고 <LF>제어수치. <LF>(개행이라고도 함)은 Unix 텍스트의 줄 구분 기호이지만 터미널에서는 줄을 나누기만 합니다(커서를 한 위치 아래로 이동). 따라서 커널의 터미널 드라이버는 실제로 이를 <CR>(화면 왼쪽 가장자리로 돌아가기), <LF>(커서 아래로 이동)( stty onlcr보통 기본적으로 켜져 있음)으로 변환합니다.

<Tab>간격을 공백으로 채우지 않고 커서를 다음 탭 정지(대부분의 터미널에서 기본적으로 8위치 떨어져 있지만 어떤 위치에든 설정되도록 구성할 수 있음)로 이동하도록 터미널에 지시합니다.

따라서 커서가 빈 줄의 시작 부분에 있는 동안 8열마다 탭에서 멈추는 터미널에 이러한 문자를 보내면 다음과 같은 결과가 발생합니다.

foo     bar

화면에 인쇄된 줄입니다. 커서가 포함 라인의 세 번째 위치에 있는 동안 전송되면 xxxxyyyyzzzz다음과 같은 결과가 발생합니다.

xxfooyyybarz

탭을 지원하지 않는 터미널에서는 이러한 탭 문자를 일련의 공백으로 변환하도록 터미널 드라이버를 구성할 수 있습니다. ( stty tab3).

원래 텔레타이프의 SPC 문자는 커서를 오른쪽으로 이동한 반면 백스페이스 키( \b)는 커서를 왼쪽으로 이동했습니다. 이제 최신 터미널에서는 SPC가 오른쪽으로 이동되어 지워집니다(예상대로 공백 문자를 씁니다). 따라서 펜던트는 \bASCII보다 새로운 것이어야 합니다. 대부분의 최신 터미널에서는 실제로 <Esc>, [, 와 같은 일련의 문자입니다 C.

n문자를 왼쪽, 오른쪽, 위, 아래 또는 화면의 어느 곳으로든 이동할 수 있는 더 많은 이스케이프 시퀀스가 ​​있습니다 . 줄이나 화면 영역 등의 일부를 지울 수 있는(공백 채우기) 다른 이스케이프 시퀀스가 ​​있습니다.

vi이러한 시퀀스는 lynx, , 와 같은 시각적 응용 프로그램에서 일반적으로 사용 됩니다. mutt여기서 dialog텍스트는 화면의 아무 곳에나 기록됩니다.

모든 X11 터미널 에뮬레이터와 기타 X11이 아닌 터미널 에뮬레이터(예: GNU)에서는 이제 screen복사하여 붙여넣을 화면 영역을 선택할 수 있습니다. 편집기에 표시되는 내용의 일부를 선택할 때 vi해당 출력을 생성하는 데 사용된 모든 이스케이프 시퀀스를 복사하고 싶지는 않을 것입니다. 거기에 보이는 텍스트를 선택하고 싶습니다.

예를 들어 다음을 실행하는 경우:

printf 'abC\rAC\bB\t\e[C\b\bD\n'

abC를 입력하고 처음으로 돌아가서 로 ab바꾸고 다음 탭 정지로 AC이동 한 다음 오른쪽으로 한 열, 왼쪽으로 두 열을 입력하고 를 입력하는 편집기 세션을 시뮬레이션합니다 .CBD

바라보다:

ABC    D

즉, ABC4개의 열 간격과 D.

xterm마우스로 또는 를 선택하면 putty선택 항목에는 공백 ABC문자 4개가 저장됩니다 .DabC<CR>AC<BS>B<Tab><Esc>[C<BS><BS>D

최종적으로 선택되는 것은 printf터미널 드라이버와 터미널 에뮬레이터가 전송했지만 후처리된 것입니다.

다른 유형의 변환에 대해서는 변경 <U+0065><U+0301>( e다음에 악센트 결합)을 <U+00E9>( é사전 합성된 형식) 으로 참조하세요 xterm.

또는 echo abc궁극적으로 ABC터미널 드라이버에 의해 변환된 다음 stty olcuc.

이제 <Tab>like는 텍스트 파일( MSDOS 텍스트 파일에서도 가끔 페이지 나누기에 사용됨) <LF>에서 실제로 가끔 발견되는 몇 안 되는 제어 문자 중 하나입니다 .<CR><FF>

따라서 일부 터미널 에뮬레이터는 가능하면 복사-붙여넣기 버퍼에 복사하여 보존하도록 선택합니다(그러나 일반적으로 그렇지 않습니다 <CR>) <LF>.

gnome-terminal예를 들어 VTE 기반 터미널(예: VTE)에서 빈 줄의 출력을 선택하면 X11 선택이 실제로 , , 7 공백 대신 X11 선택에 저장되는 것을 볼 수 있습니다 .printf 'a\tb\n'gnome-terminala\tbab

그러나 의 출력에 대해서는 공백 6개의 합을 printf 'a\t\bb\n'저장하고 , 출력의 경우 공백 7개의 합을 저장합니다 .abprintf 'a\r\tb\n'ab

다른 경우에는 터미널이 실제 입력을 복사하려고 시도합니다. 예를 들어 실행 후 두 줄을 선택하면 printf 'a \nb\n'보이지 않는 후행 공백이 남습니다. 또는 LF 문자가 포함되지 않은 두 줄을 선택할 때 두 줄이 오른쪽 여백에서 줄 바꿈된 결과인 경우.

printf이제 CLIPBOARD select의 출력을 저장하려면 X11다음과 같이 직접 수행하는 것이 좋습니다.

printf 'foo\tbar\n' | xclip -sel c

xterm이것을 또는 대부분의 다른 터미널 에 붙여넣을 때 실제로 는 를 눌렀을 때 전송된 문자이기 때문에 로 xterm대체됩니다 (터미널 드라이버가 이를 다시 변환할 수 있음).\n\rxtermEnter\n

관련 정보