"sed" 내부 변경사항을 보고하는 방법

"sed" 내부 변경사항을 보고하는 방법

sed내부 문자열 대체를 사용할 때 (이전 파일과 새 파일 간의 차이점에 의존하지 않고) 변경 사항을 보고하도록 하는 방법이 있습니까?

예를 들어 명령줄을 변경하는 방법은 다음과 같습니다.

find . -type f | xargs sed -i 's/abc/def/g'

그럼 변경사항이 즉시 표시되나요?

답변1

시스템에서 지원하는 경우 seds w플래그를 와 함께 사용할 수 있습니다 /dev/stderr. 예를 들어 다음을 입력합니다./dev/tty/dev/fd/2file

foo first
second: missing
third: foo
none here

달리기

sed -i '/foo/{
s//bar/g
w /dev/stdout
}' file

산출:

bar first
third: bar

file내용은 다음과 같이 변경 되었지만

bar first
second: missing
third: bar
none here

따라서 귀하의 경우 다음을 실행하십시오.

find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
s//bar/g
w /dev/fd/2
}' {} \;

파일을 제자리에서 편집하고 다음을 출력합니다.

./파일 1:
바 물건
더 많은 바

./파일2:

./파일 3:
바 먼저
세 번째: 바

다음과 같이 인쇄할 수도 있습니다 original line >>> modified line.

find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
h
s//bar/g
H
x
s/\n/ >>> /
w /dev/fd/2
x
}' {} \;

파일을 제자리에서 편집하고 출력합니다.

./파일 1:
foo 물건 >>> 바 물건
더 많은 foo >>> 더 많은 바

./파일2:

./파일 3:
foo 먼저 >>> bar 먼저
세 번째: foo >>> 세 번째: bar

답변2

p첫 번째 단계에서 rint 작업을 사용하여 두 단계로 이 작업을 수행할 수 있습니다.

find . -type f | xargs sed --quiet 's/abc/def/gp'

여기서 --quietsed는 모든 줄을 표시하지 않고 psuffix는 대체 항목과 일치하는 줄만 표시합니다.

sed가 표시하지 않는 제한 사항이 있습니다.어느파일이 변경되고 있는데, 이는 좀 더 복잡하게 수정하면 확실히 해결될 수 있습니다.

답변3

나는 이것이 가능하다고 생각하지 않지만 해결 방법은 대신 Perl을 사용하는 것일 수 있습니다.

find . -type f -exec perl -i -pe 's/abc/def/ && print STDERR' {} +

이것은 인쇄됩니다변경됨표준 오류에 대한 라인입니다. 예를 들어:

$ cat foo
fooabcbarabc
blah blah
$ find . -type f -exec perl -i -pe 's/abc/def/ && print STDERR' {} +
foodefbarabc
$ cat foo
foodefbarabc
blah blah

좀 더 복잡하게 만들어 줄 번호, 파일 이름, 원래 줄, 변경된 줄을 인쇄할 수도 있습니다.

$ find . -type f -exec perl -i -pe ' 
   $was=$_; chomp($was);
   s/abc/def/ && print STDERR "$ARGV($.): $was : $_"
   close ARGV if eof' {} +
./foo(1): fooabcbarabc : foodefbarabc

각 파일 간에 재설정이 close ARGV if eof필요하다는 점에 유의하세요 $..

첫 번째 줄뿐만 아니라 각 줄에 나타나는 모든 항목을 바꾸려면 연산자 g에 플래그를 추가하세요 .s///

답변4

나는 @terdon의 솔루션을 좋아합니다. Perl이 이에 유용합니다.

조정된 버전은 다음과 같습니다.

  • 일치하는 문자열이 없는 파일은 변경하려고 시도하지 않습니다.
  • 변경된 파일의 이전 버전을 백업합니다(.bak 버전 생성).
  • 각 파일/변경되지 않은 행을 나열하고 읽기 쉽도록 해당 행의 이전 버전과 새 버전을 들여쓰기하고 아래에 배치합니다.

암호

find /tmp/test -type f ! -name "*.bak" -exec grep -l '/opt/gridmon' {} \; | xargs -L1 perl -ni'.bak' -e'$old=$_; s/\/opt\/gridmon/~/g && print STDERR "$ARGV($.):\n\tOLD:$old\tNEW:$_"'

예제 출력

/tmp/test/test4.cfg(13):
    OLD:    ENVFILE /opt/gridmon/server/etc/gridmonserver.cfg
    NEW:    ENVFILE ~/server/etc/gridmonserver.cfg
/tmp/test/test4.cfg(24):
    OLD:    ENVFILE /opt/gridmon/server/etc/gridmonserver.cfg
    NEW:    ENVFILE ~/server/etc/gridmonserver.cfg

관련 정보