[bash] bash를 사용하여 파일 (인수)을 “제자리”에서 편집하는 명령을 어떻게 실행합니까?

sortbash 의 명령 으로 정렬하려는 temp.txt 파일이 있습니다 .

정렬 된 결과가 원본 파일을 대체하고 싶습니다.

예를 들어 이것은 작동하지 않습니다 (빈 파일이 생겼습니다).

sortx temp.txt > temp.txt

임시 파일에 복사하지 않고 한 줄로이 작업을 수행 할 수 있습니까?


편집 :이 -o옵션은 sort. 내가 사용하는 sort예를 들어 내 질문에. 다른 명령과 동일한 문제가 발생합니다.

uniq temp.txt > temp.txt.

더 나은 일반 솔루션이 있습니까?



답변

sort temp.txt -o temp.txt


답변

A sort는 출력을 시작하기 전에 모든 입력을 확인해야합니다. 이러한 이유로 sort프로그램은 파일을 내부에서 수정하는 옵션을 쉽게 제공 할 수 있습니다.

sort temp.txt -o temp.txt

구체적으로, GNU 문서sort 는 다음 같이 말합니다.

일반적으로 sort는 출력 파일을 열기 전에 모든 입력을 읽으므로 sort -o F F및 같은 명령을 사용하여 파일을 제자리에 안전하게 정렬 할 수 있습니다 cat F | sort -o F. 그러나, sort--merge( -m) 명령 같은, 모든 입력을 읽기 전에 출력 파일을 열 수 있습니다 cat F | sort -m -o F - G종류의 쓰기 시작 하듯이 안전하지 F전에 cat를 읽어 이루어집니다.

BSD의 문서 sort는 다음 과 같이 말합니다.

[the] output-file이 입력 파일 중 하나 인 경우 sort는 출력을 정렬하고 [the] output-file에 쓰기 전에 임시 파일에 복사합니다.

과 같은 명령 uniq은 입력 읽기를 완료하기 전에 출력 쓰기를 시작할 수 있습니다. 이러한 명령은 일반적으로 내부 편집을 지원하지 않으며이 기능을 지원하기가 더 어렵습니다.

일반적으로 임시 파일을 사용하여이 문제를 해결하거나 중간 파일을 사용하지 않으려는 경우 버퍼를 사용하여 전체 결과를 저장하기 전에 작성할 수 있습니다. 예를 들면 다음과 perl같습니다.

uniq temp.txt | perl -e 'undef $/; $_ = <>; open(OUT,">temp.txt"); print OUT;'

여기서 perl 부분은 uniqin 변수 에서 전체 출력을 읽은 $_다음이 데이터로 원본 파일을 덮어 씁니다. 선택한 스크립팅 언어, 아마도 Bash에서도 똑같이 할 수 있습니다. 그러나 전체 파일을 저장하려면 충분한 메모리가 필요하므로 대용량 파일로 작업 할 때는 권장되지 않습니다.


답변

여기에 좀 더 일반적인 접근 방식이 있으며 uniq, sort 및 기타와 함께 작동합니다.

{ rm file && uniq > file; } < file


답변

스펀지에 대한 토부의 논평 은 그 자체로 답이 될 것을 보증한다.

moreutils 홈페이지 에서 인용하려면 :

아마도 지금까지 moreutils에서 가장 일반적인 도구는 sponge (1)으로, 다음과 같은 작업을 할 수 있습니다 :

% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd

그러나 Steve Jessop이 여기에 언급sponge 한 것과 동일한 문제 가 있습니다. 파이프 라인의 명령 중 하나라도 sponge실패하면 원본 파일을 덮어 씁니다.

$ mistyped_command my-important-file | sponge my-important-file
mistyped-command: command not found

어-오, my-important-file사라졌습니다.


답변

여기에 한 줄이 있습니다.

sort temp.txt > temp.txt.sort && mv temp.txt.sort temp.txt

기술적으로는 임시 파일에 대한 복사가 없으며 ‘mv’명령은 즉각적이어야합니다.


답변

나는 sort file -o file대답을 좋아 하지만 같은 파일 이름을 두 번 입력하고 싶지 않습니다.

BASH 히스토리 확장 사용 :

$ sort file -o !#^

를 누르면 현재 줄의 첫 번째 인수를 가져옵니다 enter.

내부 고유 정렬 :

$ sort -u -o file !#$

현재 줄의 마지막 인수를 가져옵니다.


답변

많은 사람들이 -o 옵션 을 언급했습니다 . 다음은 맨 페이지 부분입니다.

man 페이지에서 :

   -o output-file
          Write output to output-file instead of to the  standard  output.
          If  output-file  is  one of the input files, sort copies it to a
          temporary file before sorting and writing the output to  output-
          file.