탭으로 구분된 두 개의 문자열을 인쇄하려고 합니다. 나는 시도했다:
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 bar
을 printf
출력합니다 foo<TAB>bar<LF>
.
f
, o
, b
및 a
은 r
단일 각도 그래픽 문자입니다.
이러한 문자를 수신한 후 터미널은 해당 문자를 표시하고 커서가 화면의 오른쪽 가장자리(원래 텔레타이프 기계의 용지)에 도달하지 않는 한 오른쪽으로 한 열 이동합니다. 이 경우 라인을 입력할 수 있습니다. 터미널과 구성 방식에 따라 화면 왼쪽 가장자리로 돌아가거나(개행) 문자를 삭제합니다.
<Tab>
그리고 <LF>
두제어수치. <LF>
(개행이라고도 함)은 Unix 텍스트의 줄 구분 기호이지만 터미널에서는 줄을 나누기만 합니다(커서를 한 위치 아래로 이동). 따라서 커널의 터미널 드라이버는 실제로 이를 <CR>
(화면 왼쪽 가장자리로 돌아가기), <LF>
(커서 아래로 이동)( stty onlcr
보통 기본적으로 켜져 있음)으로 변환합니다.
<Tab>
간격을 공백으로 채우지 않고 커서를 다음 탭 정지(대부분의 터미널에서 기본적으로 8위치 떨어져 있지만 어떤 위치에든 설정되도록 구성할 수 있음)로 이동하도록 터미널에 지시합니다.
따라서 커서가 빈 줄의 시작 부분에 있는 동안 8열마다 탭에서 멈추는 터미널에 이러한 문자를 보내면 다음과 같은 결과가 발생합니다.
foo bar
화면에 인쇄된 줄입니다. 커서가 포함 라인의 세 번째 위치에 있는 동안 전송되면 xxxxyyyyzzzz
다음과 같은 결과가 발생합니다.
xxfooyyybarz
탭을 지원하지 않는 터미널에서는 이러한 탭 문자를 일련의 공백으로 변환하도록 터미널 드라이버를 구성할 수 있습니다. ( stty tab3
).
원래 텔레타이프의 SPC 문자는 커서를 오른쪽으로 이동한 반면 백스페이스 키( \b
)는 커서를 왼쪽으로 이동했습니다. 이제 최신 터미널에서는 SPC가 오른쪽으로 이동되어 지워집니다(예상대로 공백 문자를 씁니다). 따라서 펜던트는 \b
ASCII보다 새로운 것이어야 합니다. 대부분의 최신 터미널에서는 실제로 <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
이동 한 다음 오른쪽으로 한 열, 왼쪽으로 두 열을 입력하고 를 입력하는 편집기 세션을 시뮬레이션합니다 .C
B
D
바라보다:
ABC D
즉, ABC
4개의 열 간격과 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 abc
궁극적으로 ABC
터미널 드라이버에 의해 변환된 다음 stty olcuc
.
이제 <Tab>
like는 텍스트 파일( MSDOS 텍스트 파일에서도 가끔 페이지 나누기에 사용됨) <LF>
에서 실제로 가끔 발견되는 몇 안 되는 제어 문자 중 하나입니다 .<CR>
<FF>
따라서 일부 터미널 에뮬레이터는 가능하면 복사-붙여넣기 버퍼에 복사하여 보존하도록 선택합니다(그러나 일반적으로 그렇지 않습니다 <CR>
) <LF>
.
gnome-terminal
예를 들어 VTE 기반 터미널(예: VTE)에서 빈 줄의 출력을 선택하면 X11 선택이 실제로 , , 7 공백 대신 X11 선택에 저장되는 것을 볼 수 있습니다 .printf 'a\tb\n'
gnome-terminal
a\tb
a
b
그러나 의 출력에 대해서는 공백 6개의 합을 printf 'a\t\bb\n'
저장하고 , 출력의 경우 공백 7개의 합을 저장합니다 .a
b
printf 'a\r\tb\n'
a
b
다른 경우에는 터미널이 실제 입력을 복사하려고 시도합니다. 예를 들어 실행 후 두 줄을 선택하면 printf 'a \nb\n'
보이지 않는 후행 공백이 남습니다. 또는 LF 문자가 포함되지 않은 두 줄을 선택할 때 두 줄이 오른쪽 여백에서 줄 바꿈된 결과인 경우.
printf
이제 CLIPBOARD select의 출력을 저장하려면 X11
다음과 같이 직접 수행하는 것이 좋습니다.
printf 'foo\tbar\n' | xclip -sel c
xterm
이것을 또는 대부분의 다른 터미널 에 붙여넣을 때 실제로 는 를 눌렀을 때 전송된 문자이기 때문에 로 xterm
대체됩니다 (터미널 드라이버가 이를 다시 변환할 수 있음).\n
\r
xterm
Enter\n