programing

파일에서 찾기 및 바꾸기 및 파일 덮어 쓰기가 작동하지 않고 파일을 비 웁니다.

nasanasas 2020. 10. 3. 10:53
반응형

파일에서 찾기 및 바꾸기 및 파일 덮어 쓰기가 작동하지 않고 파일을 비 웁니다.


명령 줄을 통해 HTML 파일에서 찾기 및 바꾸기를 실행하고 싶습니다.

내 명령은 다음과 같습니다.

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html

이것을 실행하고 나중에 파일을 보면 비어 있습니다. 내 파일의 내용을 삭제했습니다.

파일을 다시 복원 한 후 실행하면 :

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

stdout파일의 내용이고, 찾아 실행 된 대체합니다.

왜 이런 일이 발생합니까?


쉘이 보고 > index.html명령 줄에서 파일이 열립니다 index.html에 대한 쓰기 모든 이전 내용을 닦아.

이 문제를 해결하려면 인라인으로 변경하고 원본 파일의 백업을 생성하는 -i옵션 을 전달해야합니다 sed.

sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

.bak가 없으면 Mac OSX와 같은 일부 플랫폼에서 명령이 실패합니다.


대안적이고 유용한 패턴은 다음과 같습니다.

sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html

이는 -i옵션 을 사용하지 않고 거의 동일한 효과를 가지며 추가적으로 sed 스크립트가 어떤 이유로 실패하더라도 입력 파일이 방해받지 않는다는 것을 의미합니다. 또한 편집이 성공하면 백업 파일이 남아 있지 않습니다. 이런 종류의 관용구는 Makefile에서 유용 할 수 있습니다.

상당히 많은 seds에 -i옵션이 있지만 전부는 아닙니다. posix sed는 그렇지 않은 것입니다. 따라서 이식성을 목표로한다면 피하는 것이 가장 좋습니다.


sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html

이것은 index.html 파일에 대한 전역 내부 대체를 수행합니다. 문자열을 인용하면 쿼리 및 교체에서 공백 문제를 방지 할 수 있습니다.


sed의 -i 옵션을 사용하십시오.

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html

여러 파일을 변경하려면 (그리고 각각의 백업을 * .bak로 저장) :

perl -p -i -e "s/\|/x/g" *  

디렉토리에있는 모든 파일을 가지고 대체 할 |x는 "펄 파이"라고이 (쉽게 파이)


-i내부 편집 옵션 사용해야합니다 .


sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

추가 할 링크가 있으면 이것을 시도하십시오. 위와 같이 URL (https로 시작하고 여기서 .com으로 끝남)을 검색하고 URL 문자열로 바꿉니다. $pub_url여기 에 변수를 사용했습니다 . s여기서는 검색을 g의미하고 글로벌 교체를 의미합니다.

효과가있다 !


경고 : 이것은 위험한 방법입니다! Linux의 i / o 버퍼를 남용하고 특정 버퍼링 옵션을 사용하여 작은 파일을 처리합니다. 흥미로운 호기심입니다. 그러나 실제 상황에 사용하지 마십시오!

당신 -i옵션 외에도 유틸리티를sed 사용할 수 있습니다 .tee

에서 man:

tee-표준 입력에서 읽고 표준 출력 및 파일에 쓰기

따라서 해결책은 다음과 같습니다.

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html

-여기서는 tee파이프 라인이 버퍼링되었는지 확인하기 위해 반복됩니다. 그런 다음 파이프 라인의 모든 명령은 작업 할 입력을받을 때까지 차단됩니다. 파이프 라인의 각 명령은 업스트림 명령이 명령 입력에 1 개의 바이트 버퍼 (크기는 어딘가에 정의 됨 )를 기록 할 때 시작됩니다 . 따라서 tee index.html쓰기 위해 파일을 열어 비우는 마지막 명령 은 업스트림 파이프 라인이 완료되고 출력이 파이프 라인 내의 버퍼에있는 후에 실행됩니다.

다음은 작동하지 않을 가능성이 높습니다.

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html

-- it will run both commands of the pipeline at the same time without any blocking. (Without blocking the pipeline should pass the bytes line by line instead of buffer by buffer. Same as when you run cat | sed s/bar/GGG/. Without blocking it's more interactive and usually pipelines of just 2 commands run without buffering and blocking. Longer pipelines are buffered.) The tee index.html will open the file for writing and it will be emptied. However, if you turn the buffering always on, the second version will work too.


The problem with the command

sed 'code' file > file

is that file is truncated by the shell before sed actually gets to process it. As a result, you get an empty file.

The sed way to do this is to use -i to edit in place, as other answers suggested. However, this is not always what you want. -i will create a temporary file that will then be used to replace the original file. This is problematic if your original file was a link (the link will be replaced by a regular file). If you need to preserve links, you can use a temporary variable to store the output of sed before writing it back to the file, like this:

tmp=$(sed 'code' file); echo -n "$tmp" > file

Better yet, use printf instead of echo since echo is likely to process \\ as \ in some shells (e.g. dash):

tmp=$(sed 'code' file); printf "%s" "$tmp" > file

And the ed answer:

printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html

To reiterate what codaddict answered, the shell handles the redirection first, wiping out the "input.html" file, and then the shell invokes the "sed" command passing it a now empty file.


You can use Vim in Ex mode:

ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
  1. % select all lines

  2. x save and close


I was searching for the option where I can define the line range and found the answer. For example I want to change host1 to host2 from line 36-57.

sed '36,57 s/host1/host2/g' myfile.txt > myfile1.txt

You can use gi option as well to ignore the character case.

sed '30,40 s/version/story/gi' myfile.txt > myfile1.txt

With all due respect to the above correct answers, it's always a good idea to "dry run" scripts like that, so that you don't corrupt your file and have to start again from scratch.

Just get your script to spill the output to the command line instead of writing it to the file, for example, like that:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

OR

less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 

This way you can see and check the output of the command without getting your file truncated.

참고URL : https://stackoverflow.com/questions/5171901/find-and-replace-in-file-and-overwrite-file-doesnt-work-it-empties-the-file

반응형