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


9

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

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

둘 다 인쇄합니다.

foo     bar

두 개 사이의 공백이 실제로 5 칸인 경우 (퍼티에서 마우스로 출력을 선택하는 경우).

또한 명령을 입력 할 때 CTRL + V를 사용하고 Tab 키를 눌러 동일한 결과를 시도했습니다.

탭을 탭으로 인쇄하는 올바른 방법은 무엇입니까? 출력을 선택하고 탭을 사용하여 다른 곳으로 복사 할 수 있습니까?

그리고 두 번째 질문 : bash가 왜 탭을 공백으로 확장합니까?

업데이트 : 분명히,이 퍼티의 문제가 : /superuser/656838/how-to-make-putty-display-tabs-within-a-file-instead-of-changing-them-to 공백



왜 탈출하지? printf '%s\\t%s\n' foo bar
Valentin Bajrami

@steeldriver 고마워요. 제가 필요로하는 것과 매우 비슷하지만 궁극적으로는 해결책이 없습니다 ...
Asu

1
@Valentin 그 출력 foo\tbar...
wjandrea

1
그럼에도 불구하고 터미널에 문제가 있음을 이미 알고 있음에도 불구하고 Bash 자체 $'\t'는 tabulator로 해석 됩니다. 따라서 다음과 같이 문자열을 항상 연결할 수 있습니다 (예 : 할당). v='This is'$'\t''a test'문자 그대로 인쇄합니다.printf '%s' "$v"
rexkogitans

답변:


9

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

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


3
tty 드라이버를 실행 한 후에도 수행 할 수 있습니다 stty tab3.
Stéphane Chazelas

14

둘 사이의 공백은 실제로 5 개의 공백입니다.

아뇨. echo또는 의 출력에 없습니다 printf.

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

탭을 탭으로 인쇄하는 올바른 방법은 무엇입니까? 출력을 선택하고 탭을 사용하여 다른 곳으로 복사 할 수 있습니까?

이것은 다른 문제입니다. 셸이 아니라 터미널 에뮬레이터로 탭을 출력 공간으로 변환합니다. 전부는 아니지만 많은 사람들이 그렇게합니다.

탭이있는 출력을 파일로 리디렉션하고 파일에서 복사하거나 unexpand공백을 탭으로 변환하기 위해 출력에 사용 하는 것이 더 쉬울 수 있습니다 . (또한 공백으로 시작하는 탭이 무엇인지 알 수 없으며 가능한 경우 모든 공백을 탭으로 변환합니다.) 물론 이것은 출력과 관련하여 정확히 무엇을 해야하는지에 달려 있습니다.


출력을 선택하려고하면 5 공백으로 처리됩니다. 명령 출력 내용을 확인하는 'od -c'에 감사합니다.
Asu December

1
@Asu 나는 그가 그것을 이해한다고 생각합니다. 그의 해결책은 터미널 에뮬레이터가 창에서 탭을 선택할 때 탭을 탭으로 남겨 두는 것을 보장하지 않기 때문에 다른 수단을 통해 출력을 얻는 것입니다. 그러나 방금 확인했지만 퍼티, xterm 및 konsole은 탭을 공백으로 변환하지만 urxvt 및 gnome-terminal은 그렇지 않습니다. 따라서 다른 해결책은 터미널을 전환하는 것입니다.
JoL

@JoL 그렇습니다. 그것이 바로 1 분 전에 온 결론입니다. 누군가가 그런 식으로 글을 올리려고한다면 이것이 받아 들여질 것입니다.
Asu

1
@Asu, 예, 문제를 수동으로 해결하는 것에 대해 생각했습니다. 그렇게 해야하는 것은 성가 시겠지만 탭 복사를 지원하는 터미널 에뮬레이터가 있다는 것을 깨닫지 못했습니다. 그렇게하는 것으로 변경하면 물론 훨씬 더 나은 솔루션입니다!
ilkkachu

4

에서 printf '%s\t%s\n' foo bar, printf출력을한다 foo<TAB>bar<LF>.

f, o, b, ar단일 폭 그래픽 문자입니다.

이러한 문자를 수신하면 터미널은 해당 글리프를 표시하고 커서가 이미 화면의 오른쪽 가장자리 (원래 텔레 타이프 라이터의 용지)에 도달하지 않는 한 열을 오른쪽으로 이동합니다. 화면의 왼쪽 가장자리로 돌아가거나 (줄 바꿈) 터미널과 구성 방법에 따라 문자를 버립니다.

<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 터미널 에뮬레이터와 GNU와 같은 X11이 아닌 다른 것들은 screen복사 붙여 넣기를위한 화면 영역을 선택할 수있게합니다. vi편집기 에서 볼 수있는 부분을 선택하면 해당 출력을 생성하는 데 사용 된 모든 이스케이프 시퀀스를 복사하지 않습니다. 거기에 표시되는 텍스트를 선택하려고합니다.

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

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

입력 편집기 세션을 시뮬레이션하는 abC대체, 처음으로 돌아가 abAC, C함께 B입력 한 다음, 왼쪽으로 다음, 오른쪽으로 한 후, 다음 탭 정지에, 두 개의 열을 한 번 더 열을 이동 D.

당신은 볼 :

ABC    D

즉, ABC4 열 간격과 D입니다.

마우스로 xterm또는 putty을 사용하여 선택 ABC하면 4 개의 공백 문자가 D아닌 선택 영역에 저장됩니다 abC<CR>AC<BS>B<Tab><Esc>[C<BS><BS>D.

선택에서 끝나는 printf것은 터미널 드라이버와 터미널 에뮬레이터에 의해 전송 되었지만 후 처리 된 것입니다.

변형의 다른 종류의 볼 <U+0065><U+0301>( e합성 급성 악센트 하였다)로 변경 <U+00E9>( é예비 이루어지는 형태)에 의해 xterm.

또는 . 후에 터미널로 보내기 전에 터미널 드라이버 echo abcABC의해 변환됩니다 stty olcuc.

이제는 실제로 텍스트 파일 ( MSDOS 텍스트 파일 및 페이지 나누기) 에있는 몇 가지 제어 문자 중 하나 <Tab>와 같습니다 .<LF><CR><FF>

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

예를 들어와 같은 VTE 기반 터미널 에서 빈 줄 gnome-terminal의 출력을 선택할 때 실제로는 7 개의 공백과 X 대신에 X11 선택 항목에 저장 되는 것을 볼 수 있습니다.printf 'a\tb\n'gnome-terminala\tbab

그러나의 출력 printf 'a\t\bb\n',이를 저장 a, 6 개 및 공간 b등에 대한 printf 'a\r\tb\n', a7 개 공간과 b.

printf 'a \nb\n'보이지 않는 후행 공간이 유지 되는 곳에서 실행 후 두 줄을 선택할 때처럼 터미널이 실제 입력을 복사하려고하는 다른 경우 가 있습니다. 또는 두 줄을 선택할 때 두 줄이 오른쪽 여백으로 줄 바꿈 될 때 LF 문자가 포함되지 않습니다.

이제 printfCLIPBOARD X11select에 출력을 저장하려면 다음과 같이 직접 수행하는 것이 가장 좋습니다.

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

주 당신이 있음을 붙여 넣을 때 xterm대부분의 다른 단자 나, xterm실제로 대체 \n\r그 문자 때문에 xterm누를 때 전송 Enter(그리고 터미널 드라이버가 다시로 번역 할 수있다 \n).


매우 통찰력이 있습니다. 감사합니다. xclip 솔루션을 시도했지만 작동합니다. 그러나 그것은 내가 생각했던 것을 정확하게하지 않으며 X11이 필요합니다. 이것은 어느 시점에서 유용 할 것입니다, 감사합니다!
Asu December

@Asu는 X11같은 단말기 에뮬레이터에서 복사 - 붙여 넣기 선택 처리 무엇 xterm또는 putty유닉스한다. 다른 터미널 에뮬레이터에는 자체 복사-붙여 넣기 메커니즘과 GNU 화면 의 readbufregister명령 과 같이 임의의 내용을 저장하는 방법이있을 수 있습니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.