sed 및 grep / egrep을 사용하여 검색 및 바꾸기


97

egrep -R다음과 같이 약 10 개의 공용체를 포함하는 정규식을 사용 하고 있습니다. .jpg | .png | .gif등이 잘 작동합니다. 이제 찾은 모든 문자열을 다음과 같이 바꾸고 싶습니다..bmp

나는 뭔가를 생각하고 있었다

egrep -lR "\.jpg|\.png|\.gif" . | sed "s/some_expression/.jpg/" file_it_came_form

그래서 여기서 문제는 비슷한 통합 정규식 sed을 어떻게 수행하고 입력을 얻은 파일에 변경 사항을 저장하도록 지시하는 방법입니다.


2
디렉토리 계층 구조에서 여러 파일을 검색하고 바꾸는 방법을 검색하는 동안이 질문을 발견했습니다. 내 상황에있는 다른 사람들을 위해 rpl을 시도하십시오 .
titaniumdecoy

감사합니다 rpl 작동하고 기억하기 정말 쉽습니다 .. 단지 rpl old_string new_string target_files.
cesarpachon 15.06.24

답변:


183

다음 명령을 사용하십시오.

egrep -lRZ "\.jpg|\.png|\.gif" . \
    | xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
  • egrep: 확장 정규식을 사용하여 일치하는 줄 찾기

    • -l: 일치하는 파일 이름 만 나열

    • -R: 주어진 모든 디렉토리를 재귀 적으로 검색

    • -Z: \0레코드 구분자로 사용

    • "\.jpg|\.png|\.gif": 문자열 중 하나와 일치 ".jpg", ".gif"또는".png"

    • .: 현재 디렉토리에서 검색 시작

  • xargs: stdin을 인수로 사용하여 명령 실행

    • -0: \0레코드 구분자로 사용 합니다. 입력 파일 이름의 공백과 줄 바꿈에 속지 않도록 -Zof egrep와 일치하는 것이 중요합니다 .

    • -l: 명령 당 한 줄을 매개 변수로 사용

  • sed: s tream ed itor

    • -i: 백업하지 않고 입력 파일을 출력으로 대체

    • -e: 다음 인수를 표현식으로 사용

    • 's/\.jpg\|\.gif\|\.png/.bmp/g': 문자열의 모든 항목을 대체 ".jpg", ".gif"또는 ".png"함께".bmp"


모두 작동합니다. | sed 부분에서. 이해가 안되는데 ... xargs의 -l 부분이 나에게 오류를 주었기 때문에 제거했는데 관련이있을 수 있습니까?
Ori

이 명령이 처리하는 모든 파일의 끝에 개행 문자를 추가하는 것을 발견했습니다.
titaniumdecoy

@titanumdecoy :이 동작을 재현 할 수 없었습니다. 어떤 버전의 sed를 사용하고 있으며 어떤 OS에서 사용 중입니까?
David Schmitt 2011

1
@DavidSchmitt : sed -r확장 정규식 에 사용하고 싶을 것입니다 . 이 시점에서 패턴은 egrep에서 사용 된 것과 일치하며 재사용을 위해 변수에 넣을 수 있습니다.
bukzor 17:03에

이 명령은 내가 만든 라이브러리에 대한 내 앱에서 헤더 파일을 복사하는 작업 시간을 절약했습니다. 이것은 대단합니다 :) 여기 내가 사용한 명령이 egrep -lRZ "\ .h $"입니다. | xargs -0 tar -cvf headers.tar | (CP headers.tar의 헤더, CD 헤더; headers.tar XF 타르)
레이지 코더

11

솔직히, 적절한 작업을 위해 sed를 좋아하는 것처럼 이것은 확실히 perl의 작업입니다. 특히 "원래의 위치로 다시 쓰기"(perl의 -i스위치가 수행합니다. 그리고 선택적으로 예를 들어 .bak를 추가하여 이전 버전을 유지할 수 있습니다 -i.bak. 대신 사용하십시오).

perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/

sed (가능하다면) 또는 awk의 복잡한 작업보다는 ...


6
sed는 perl처럼 -i를 사용합니다.
Stobor

@Stobor-정규식 교체 문자열을 공급할 때 펄 연산이 sed와 달리 내가 원하는대로 정확히 수행하는 문제가 있었다고 맹세합니다. 정규식 옵션을 sed..에 부여 했음에도 불구 하고 sed 또는 한계가있었습니다.
meder omuraliev

10

이를 수행하는 또 다른 방법

find . -name *.xml -exec sed -i "s/4.6.0-SNAPSHOT/5.0.0-SNAPSHOT/" {} \;

위의 명령에 대한 도움말

찾기는 다음으로 표시된 현재 디렉토리에서 자동으로 찾습니다. .

-name 제 경우에는 pom.xml이 와일드 카드를 줄 수있는 파일 이름입니다.

-exec 실행하다

sed 스트림 편집기

-i 대소 문자를 무시하다

s 대용이다

/4.6.0.../ 검색 할 문자열

/5.0.0.../ 대체 할 문자열


아마도 강력하지 -하지만이 허용 대답보다 더 나를 이해하기 훨씬 쉽습니다
icc97

5

이 페이지의 명령 중 어느 것도 나를 위해 작동하지 않았습니다. sed 솔루션 은 처리 한 모든 파일의 끝에 개행 문자를 추가했으며 perl 솔루션 은 find에서 충분한 인수를 허용하지 못했습니다. 완벽하게 작동하는이 솔루션을 찾았습니다.

find . -type f -name '*.[hm]' -print0 
    | xargs -0 perl -pi -e 's/search_regex/replacement_string/g'

이것은 현재 디렉토리 트리를 반복하고 또는로 끝나는 모든 파일에서로 대체 search_regex됩니다 .replacement_string.h.m

나는 또한 과거에 이러한 목적으로 rpl 을 사용했습니다 .


0

for 루프를 사용하여 시도

 for i in `egrep -lR "YOURSEARCH" .` ; do echo  $i; sed 's/f/k/' <$i >/tmp/`basename $i`; mv /tmp/`basename $i` $i; done

예쁘지는 않지만해야합니다.


3
xargs는 확실히 여기에 더 적합합니다.
Nathan Fellman

1
그리고 사용 |while read iegrep을의 결과가 너무 오래 될 때 패턴은 제한을 스트리밍 피할 길이 수 있도록 것입니다
데이비드 슈미트

0

내 사용 사례는 다음 코드 로 대체 foo:/Drive_Letter하고 싶었습니다 foo:/bar/baz/xyz. 나는 대량의 파일이있는 동일한 디렉토리 위치에있었습니다.

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

도움이 되었기를 바랍니다.

업데이트 s | foo : / Drive_letter : | foo : / ba / baz / xyz | g


sed 명령에 다른 구분 기호를 사용할 수 있으며 이렇게하면 경로 이름이 훨씬 더 좋아집니다.sed 's|foo:/Drive_letter:|foo:/ba/baz/xyz|g'
Kevin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.