처리해야 하는 큰 파일이 있는데 작동하지 않는 것 같은 몇 가지 스크립트를 작성한 후에 파일의 행 중 일부가 실제로 탭으로 구분되지 않고 공백으로 구분되어 있음을 발견했습니다.
질문:공백으로 구분된 줄을 탭으로 구분된 줄로 변경하는 가장 좋은 방법이 무엇인지 궁금합니다.
파일에는 한 줄에 4개의 항목이 포함되어 있으며 총 약 5000개의 항목이 있으며 그 중 약 150개는 탭으로 구분되지 않고 공백으로 구분되어 있습니다.
답변1
tr ' ' '\t' < file 1<> file
각 공백 문자는 탭 문자로 대체됩니다.
사람들이 안전하지 않다고 말하는 것에 대한 응답으로:
쉘은 파일 설명자 0에서 읽기 위해 파일을 열고 읽기 및 쓰기를 위해 파일 설명자 1에서 파일을 엽니다. 이들 중 하나라도 실패하면 실행되지 않고 종료됩니다 tr
. 리디렉션이 성공하면 tr
실행됩니다 .
tr
파일을 한 번에 한 블록씩 읽고 음역한 후 수정되지 않은 블록 대신 수정된 블록을 출력합니다.
이 작업을 수행할 때 일반적으로 디스크에 공간을 할당할 필요가 없습니다. 예외는 파일이 처음부터 드물거나 파일 시스템이 쓰기 중 복사를 구현하는 경우입니다. 따라서 "사용 가능한 공간 없음" 오류가 발생할 가능성이 적습니다.
I/O 오류와 같은 다른 오류는 기본 디스크에 오류가 발생하거나 파일 시스템이 씬 프로비저닝된 블록 장치(예: LVM 스냅샷)에 있는 경우 발생할 수 있습니다. 두 경우 모두 드물고 어떤 경우에도 테이프와 관련될 수 있습니다. . 백업으로 돌아가려면
그럼에도 불구하고 write()
시스템 호출이 실패 하면 tr
오류가 보고되고 종료되어야 합니다. stdout이 읽기-쓰기 모드로 열리므로아니요잘렸습니다. 파일을 자르려면 종료 시 표준 출력을 명시적으로 호출 tr
해야 하는데 truncate()
이는 의미가 없습니다.
그러나 일어날 일은 파일이 부분적으로 음역된다는 것입니다( tr
실패할 때까지).
하지만 tr
현재 Debian sid amd64에서 발견되는 GNU에는허점write()
시스템 호출이 실패하면 세그폴트가 발생하고 표준 출력 (편집하다, 지금libc6 Debian 패키지 버전 2.19-1 이후 수정됨). 이는 실제로 파일을 손상시킵니다(하지만 다시 자르지는 않습니다).
tr ' ' '\t' < file > newfile && mv newfile file
file
올바르게 생성되지 않으면 교체되지 않지만 newfile
이와 관련된 여러 가지 문제가 있습니다.
- 이미 존재하는 것을 손상시키지 않도록 해야 합니다
newfile
(심볼릭 링크도 고려). - 현재 디렉터리에 대한 쓰기 권한이 필요합니다.
- 이 파일의 추가 복사본을 저장하려면 추가 저장 공간이 필요합니다.
- 원본 파일의 권한, 소유권, 생성 시간, 확장 속성 등이 손실됩니다.
- 원본 파일이 심볼릭 링크인 경우 일반 파일로 대체합니다.
tr ' ' '\t' < file 1<> file
perl -pi -e 's/ /\t/g'
장애가 발생하는 경우 perl
(예: 디스크 가득 참) 원본 파일을 잃고 perl
지금까지 성공적으로 출력한 파일 만 다시 가져오기 때문에 일반적인 파일보다 안전합니다 .
답변2
sed
을 사용할 수도 있습니다 .
sed -i.bak 's/ /\t/g' filename
filename.bak
파일을 편집하기 전에 파일이 생성 됩니다 .
s/ /\t/g
=> 이는 sed
파일의 모든 줄에서 공백을 탭으로 전체적으로 바꾸도록 지시합니다.
답변3
파일의 모든 공백을 탭으로 변경하려면 를 사용하십시오 tr
.
tr ' ' '\t' <input_file >output_file
하나 이상의 공백의 각 순서를 단일 탭으로 변경하려면 를 사용하십시오 sed
.
sed -e 's/ */\t/g' <input_file >output_file
일부 sed 구현은 \t
탭을 이해하고 다른 구현은 리터럴 탭을 기대합니다.
정렬된 열이 포함된 파일이 있고 가변 개수의 공백을 사용하여 열을 정렬하는 경우 탭으로 구분된 열을 갖도록 변환할 수 있습니다.unexpand
.