sed
내부 문자열 대체를 사용할 때 (이전 파일과 새 파일 간의 차이점에 의존하지 않고) 변경 사항을 보고하도록 하는 방법이 있습니까?
예를 들어 명령줄을 변경하는 방법은 다음과 같습니다.
find . -type f | xargs sed -i 's/abc/def/g'
그럼 변경사항이 즉시 표시되나요?
답변1
시스템에서 지원하는 경우 sed
s w
플래그를 와 함께 사용할 수 있습니다 /dev/stderr
. 예를 들어 다음을 입력합니다./dev/tty
/dev/fd/2
file
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'
여기서 --quiet
sed는 모든 줄을 표시하지 않고 p
suffix는 대체 항목과 일치하는 줄만 표시합니다.
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