Vim 또는 Linux에서 공백을 탭으로 변환하려면 어떻게해야합니까?


192

Stack Overflow에서 필요한 것을 찾지 않고 공백을 탭으로 변환하는 방법에 대한 몇 가지 질문을 살펴 보았습니다. 탭을 공백으로 변환하는 방법에 대한 추가 질문이 있지만 그 반대의 방법을 시도하고 있습니다.

에서 Vim내가 해봤 :retab:retab!행운을하지 않고 있지만, 내가 믿는 사람들은 어쨌든 공간으로 탭에서 진행을 위해 사실이다.

난 둘 다 노력 expandunexpand운이없이 명령 프롬프트에서.

문제의 파일은 다음과 같습니다.

http://gdata-python-client.googlecode.com/hg-history/a9ed9edefd61a0ba0e18c43e448472051821003a/samples/docs/docs_v3_example.py

또는 셸을 사용하여 선행 공백을 탭으로 변환하려면 어떻게 Vim해야합니까?


이제 삭제 된 @Matt의 주석에서 첫 번째 예제 ( sed "s/ +/`echo -e '\t'`/g" < input.py > output.py)가 선행 공백뿐만 아니라 모든 공백을 변환하는 것으로 나타납니다. 두 번째 예 ( sed "s/^ +/`echo -e '\t'`/g" < input.py > output.py)에서는 각 줄의 첫 번째 공백 만 탭으로 바꾸고 나머지는 남겨 둡니다.
cwd

반대로 관련 : 탭을 공백으로 바꾸는 방법? Vim SE에서
kenorb

모든 / 많은 파일에 대한 답변을 찾지 못했습니다 . 그래서 내 자신의 파일을 작성했습니다 : stackoverflow.com/a/44581474/1115187 . 와 함께 find, awk그리고 블랙 잭 (댓글에 남겨두기에는 너무 길다)
maxkoryukov

답변:


316

Vim을 사용하여 모든 선행 공백 을 확장하면 (보다 큼 'tabstop') 사용하는 retab것이 옳았 지만 먼저 'expandtab'재설정 :verbose set ts? et?해야합니다 (친구입니다). retab걸리는 범위를 나는 보통 지정할 수 있도록, %"전체 파일"을 의미 할 수 있습니다.

:set tabstop=2      " To match the sample file
:set noexpandtab    " Use tabs, not spaces
:%retab!            " Retabulate the whole file

이와 같은 작업 (특히 Python 파일에서)을 수행하기 전에 일반적으로을 설정 하여 공백과 변경 사항을 'list' 수 있습니다.

난에 다음과 같은 매핑이 .vimrc 이를 들어 :

nnoremap    <F2> :<C-U>setlocal lcs=tab:>-,trail:-,eol:$ list! list? <CR>

2
여기 내가 어떻게 작동하는지, 무엇이 필요한지, 무엇이 아닌지 확실하지 않으며, brea 나는 reatab이 수행되기 전에 "%"가 무엇인지 모른다. :set noet , :set tabstop=2, :retab!, :%retab!, :set tabstop=1, :retab!,:%retab!
CWD

2
왜 내가 사용하는지에 대한 설명을 포함하도록 답변을 업데이트했습니다. % . F2 매핑은 입력 한 그대로 입니다.
Johnsyweb 2012

7
특정 파일에 대해서는 다음과 같이 :set noet ts=2 |%retab!
하시면됩니다

1
@Johnsyweb이 공정하기 위해서는 틀 렸습니다 : :%retab!여전히 작동합니다. 나는 혼동하고 ==있는 등 수행 preserveindent 설정을 존중합니다.
Unk

1
커피 스크립트 파일을 공백에서 탭으로 변환하려면 @Johnsyweb의 답변 (.vimrc 파일에 대한 추가 포함)을 따랐지만 대신 :set tabstop=4
Mikeumus

38

1- 공백이 있고 탭을 원하는 경우

먼저, 하나의 탭을 가질 공간 수를 결정해야합니다. 즉, 앞에 4 개의 공백이있는 줄이 있다고 가정하거나 8 ... 탭이 4 개의 공백이되기를 원할 것입니다. 이제 그 정보로 다음을 수행하십시오.

:set ts=4
:set noet
:%retab!

여기에 문제가 있습니다! 이 일련의 명령은 줄의 시작 부분에 공백뿐만 아니라 모든 텍스트를 찾습니다. 그것은 다음과 같은 문자열을 의미합니다 : "Hey,␣this␣␣␣␣is␣4␣spaces"will 될 "Hey,␣this⇥is␣4␣spaces"것이지만 그렇지는 않습니다! 그 탭!.

이 작은 문제를 해결하기 위해 search대신을 추천합니다 retab.

:%s/^\(^I*\)␣␣␣␣/\1^I/g

이 검색은 전체 파일에서 탭 수로 시작하여 4 개의 공백으로 시작하는 행을 찾은 다음 찾은 탭 수에 1을 더한 값으로 대체합니다.

불행히도 이것은 한 번에 실행되지 않습니다!

처음에는 파일에 공백으로 시작하는 줄이 있습니다. 그러면 검색은 처음 4 개의 공백 만 탭으로 변환하고 다음을 수행합니다.

명령을 반복해야합니다. 몇 번이나? 당신이 얻을 때까지 pattern not found. 아직 프로세스를 자동화하는 방법을 생각할 수 없습니다. 그러나 당신이 할 경우 :

`10@:`

아마 끝났을 것입니다. 이 명령은 마지막 검색 / 바꾸기를 10 번 반복합니다. 프로그램에 너무 많은 들여 쓰기가 없을 것입니다. 그렇다면 다시 반복하십시오 @@.

이제 답을 완성하십시오. 나는 당신이 반대를 요구했다는 것을 알고 있지만, 언제 일을 취소해야하는지 결코 알지 못합니다.

2 탭이 있고 공백이 필요합니다.

먼저 탭을 변환 할 공간 수를 결정하십시오. 각 탭을 2 칸으로하고 싶다고합시다. 그런 다음 다음을 수행하십시오.

:set ts=2
:set et
:%retab!

이것은 문자열과 같은 문제가 있습니다. 그러나 문자열 내부에서 하드 탭을 사용하지 않는 더 좋은 프로그래밍 스타일로 실제로 여기서 좋은 일을하고 있습니다. 문자열 안에 탭이 정말로 필요하다면을 사용하십시오 \t.


매우 드문 경쟁 조건 인 것 같습니다. 어쨌든 시각적 범위 선택을 허용하는 함수를 만들고 일치하는 항목을 찾을 수 없을 때까지 검색 기능을 반복하면 더 영리하고 유용한 답변 일 것입니다.
albfan

그렇습니다. 보다 명확한 솔루션을 원한다면 함수를 사용할 수 있습니다. 어쨌든, ex command함수 내에서 수행되는 것이기 때문에 항상에서 수행하는 방법을 아는 것이 좋습니다 . 그리고 아닙니다. 드문 일이 아닙니다. 엉망으로 만들려면 공백이있는 문자열이 필요합니다. 전혀 드문 일이 아닙니다. 나는 거기에 있었다. 댓글 주셔서 감사합니다.
Dr Beco

검색을 여러 번 실행하지 않고 / g가 각 행 연속 공백에서 4 개 그룹을 모두 탭으로 변환하기에 충분하지 않은 이유를 설명하십시오.
Bjartur Thorlacius

안녕 @BjarturThorlacius, 문제는 ^기호 를 제거 하고 줄의 처음부터 검색을 시작하면 문자열 내부의 공백이 변경 될 위험이 있다는 것입니다. 을 사용하면 ^줄의 시작 이후 공백과 탭만 변경되므로 들여 쓰기가 보장됩니다. 게다가, 한 번에 모든 작업을 수행해도 괜찮다면 다음을 제거하고 ^한 번만 실행 하십시오 .:%s/\(^I*\)␣␣␣␣/\1^I/g
Dr Beco

14
:%s/\(^\s*\)\@<=    /\t/g

번역 : 4 개의 연속 공백 (= 문자 뒤)의 모든 인스턴스를 검색하지만 해당 지점까지의 전체 행이 공백 인 경우에만 해당됩니다 (이는 너비가 0 인 룩 어설 션 어설 션을 사용함 \@<=). 찾은 각 인스턴스를 탭 문자로 바꾸십시오.


1
확장 근무 유일한 해결책 1 개 공간1 개 탭 하지만,이 질문에 대해 유니 코드를 조심은 그냥 사용 :%s/\(^\s*\)\@<= /\t/g- 바로 후 (4 개 공간에 넣어 1 개 탭으로 4 개 공간 변환) 공간의 적절한 수를 넣어<=
Orwellophile

5

모든 공백을 탭으로 변경합니다 : % s / \ s / \ t / g


이것이 바로 내가 필요한 것입니다. 감사. 내가해야 할 유일한 변경 사항은 모든 단일 공간을 수행하는 대신 4 공간마다 탭으로 바꾸는 것입니다.
익명의 사람

3

리눅스 : with unexpand(andexpand )

https://stackoverflow.com/a/11094620/1115187 매우 유용한 솔루션입니다. 주로 * nix-utilities를 사용하기 때문입니다.

  1. 펼치기 — 공백-> 탭
  2. 확장 — 탭-> 공백

리눅스 : 커스텀 스크립트

내 원래 답변

4 개의 공백 들여 쓰기 ( {4}스크립트 에는 2 개 있음)를 폴더의 모든 .py파일에있는 탭 ./app(재귀 적으로)으로 바꾸는 배쉬 스 니펫 :

find ./app -iname '*.py' -type f \
    -exec awk -i inplace \
    '{ match($0, /^(( {4})*)(.*?)$/, arr); gsub(/ {4}/, "\t", arr[1]) }; { print arr[1] arr[3] }' {} \; 

가운데 나 끝에있는 4 개의 공백은 수정하지 않습니다.

Ubuntu 16.0x 및 Linux Mint 18에서 테스트되었습니다.


0

필자의 경우 탭으로 대체하려는 여러 공백 (필드가 하나 이상의 공백으로 구분됨)이있었습니다. 다음과 같이했습니다.

:% s/\s\+/\t/g

0

GNU coreutils가 설치되어 %!unexpand --first-only있거나 4 개의 공백 탭을 고려한 경우 %!unexpand -t 4 --first-only( --first-only실수로 호출 unexpand한 경우에만 있음)을 고려하십시오 --all.

이는 지정된 탭 정지 앞의 공백 만 대체하고 그 다음 공백은 대체 하지 않습니다 . 문자 그대로 탭을 표시하지 않으면 vim에 시각적 차이가 없습니다. 예를 들어, 내 ~/.vimrc포함 set list listchars=tab:▸┈(이것이 당신이 unexpand작동하지 않았다고 생각하는 이유입니다 ).


0

Vim을 사용하여 파일 공간 (예 : 디렉토리 계층의 모든 * .ts 파일)을 2 칸에서 4 칸으로 다시 탭하려면 명령 줄에서 다음을 시도하십시오.

find . -name '*.ts' -print0 | xargs -0 -n1 vim -e '+set ts=2 noet | retab! | set ts=4 et | retab | wq'

이 작업은 find일치하는 모든 파일을 전달 하는 데 사용 됩니다 xargs(찾기에서 -print0 옵션은 이름에 공백이있는 파일을 처리하기 위해 -0 옵션과 함께 xargs에 적용됩니다).

xargs -e는 실제로 여러 명령 인 지정된 ex 명령을 실행하는 각 파일 에서 exm 모드 ( )에서 vim을 실행하여 기존 선행 공백을 탭으로 변경하고, 탭 중지를 재설정하고 탭을 다시 공백으로 변경하고 마지막으로 저장하고 종료합니다.

ex 모드에서 실행하면 Vim: Warning: Input is not from a terminal각 파일에 대해 다음 을 방지 할 수 있습니다.


-1

간단한 파이썬 스크립트 :

import os

SOURCE_ROOT = "ROOT DIRECTORY - WILL CONVERT ALL UNDERNEATH"

for root, dirs, files in os.walk(SOURCE_ROOT):
    for f in files:
        fpath = os.path.join(root,f)
        assert os.path.exists(fpath)
        data = open(fpath, "r").read()
        data = data.replace("    ", "\t")
        outfile = open(fpath, "w")
        outfile.write(data)
        outfile.close()

하나의 큰 문제는이 조각은 대체 모든 4-공간 뿐만 아니라, 들여 쓰기 (줄의 시작 부분에)
maxkoryukov

두 번째 : 파일 필터가 구현되지 않습니다
maxkoryukov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.