IT story

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

hot-time 2020. 8. 5. 07:46
반응형

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 Fand 같은 명령을 사용하여 파일을 안전하게 정렬 할 수 있습니다 cat F | sort -o F. 그러나, sort--merge( -m) 명령 같은, 모든 입력을 읽기 전에 출력 파일을 열 수 있습니다 cat F | sort -m -o F - G종류의 쓰기 시작 하듯이 안전하지 F전에 cat를 읽어 이루어집니다.

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

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

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

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

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

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


보다 일반적인 접근 방식은 다음과 같습니다.

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

스폰지에 대한 Tobu의 의견 은 그 자체로 답이 될 것을 보증합니다.

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 옵션 을 언급했습니다 . 여기 맨 페이지 부분이 있습니다.

매뉴얼 페이지에서 :

   -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.

이것은 메모리가 많이 제한되어 있지만 awk를 사용하여 중간 데이터를 메모리에 저장 한 다음 다시 쓸 수 있습니다.

uniq temp.txt | awk '{line[i++] = $0}END{for(j=0;j<i;j++){print line[j]}}' > temp.txt

sponge보다 일반적인 대안 sed:

sed -ni r<(command file) file

그것은 어떤 명령 (작동 sort, uniq, tac, ...)와 사용 매우 잘 알려진 sed'의 -i옵션 (현재 위치에서 편집 파일).

경고 :command file 파일을 적절히 편집하는 것은 본질적으로 안전하지 않으므로 먼저 시도하십시오 .


설명

Firstly, you're telling sed not to print the (original) lines (-n option), and with the help of the sed's r command and bash's Process Substitution, the generated content by <(command file) will be the output saved in place.


Making things even easier

You can wrap this solution into a function:

ip_cmd() { # in place command
    CMD=${1:?You must specify a command}
    FILE=${2:?You must specify a file}
    sed -ni r<("$CMD" "$FILE") "$FILE"
}

Example

$ cat file
d
b
c
b
a

$ ip_cmd sort file
$ cat file
a
b
b
c
d

$ ip_cmd uniq file
$ cat file
a
b
c
d

$ ip_cmd tac file
$ cat file
d
c
b
a

$ ip_cmd
bash: 1: You must specify a command
$ ip_cmd uniq
bash: 2: You must specify a file

Use the argument --output= or -o

Just tried on FreeBSD:

sort temp.txt -otemp.txt

To add the uniq capability, what are the downsides to:

sort inputfile | uniq | sort -o inputfile

Read up on the non-interactive editor, ex.


If you insist on using the sort program, you have to use a intermediate file -- I don't think sort has an option for sorting in memory. Any other trick with stdin/stdout will fail unless you can guarantee that the buffer size for sort's stdin is big enough to fit the entire file.

Edit: shame on me. sort temp.txt -o temp.txt works excellent.


Another solution:

uniq file 1<> file

참고URL : https://stackoverflow.com/questions/146435/how-do-i-execute-any-command-editing-its-file-argument-in-place-using-bash

반응형