"sed"전체 변경 사항을보고하는 방법


23

현재 sed위치에서 문자열을 바꾸는 데 사용할 때 이전 및 새 파일의 차이에 의존하지 않고 변경 사항을보고하는 방법이 있습니까?

예를 들어, 명령 행을 어떻게 변경할 수 있습니까

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

변경 사항을 즉시 확인할 수 있습니까?

답변:


15

당신은 사용할 수 sedw중 하나와 플래그를 /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
}' {} \;

파일을 내부 편집하고 출력합니다.

./file1 :
바 물건
더 많은 바

./file2 :

./file3 :
먼저 바
셋째 : 바

다음과 같은 것을 인쇄 할 수도 있습니다 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
}' {} \;

파일을 내부 편집하고 출력합니다.

./file1 :
foo stuff >>> 바 물건
더 많은 foo >>> 더 많은 바

./file2 :

./file3 :
foo first >>> 바 먼저
셋째 : foo >>> 셋째 : 바

16

p첫 번째 패스 에서 rint 조치 를 사용하여 다음 두 단계로 수행 할 수 있습니다.

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

여기서 --quietsed는 모든 행을 표시하지 않으며 p접미사는 대체와 일치하는 행만 표시합니다.

이것은 sed가 어떤 파일이 변경되고 있는지 보여주지 않을 것 입니다.


두 번의 패스가 필요하기 때문에 원하는 것을하지는 않지만이 p를 배웠기 때문에 투표하고 있습니다. 매우 유용합니다. 특히 말한 것처럼 파일도 인쇄 된 경우입니다. 비슷한 것for x in `find . -type f`; do echo ///File $x: ; sed --quiet 's/abc/def/gp' $x; done
ricab

@ msw 나는 많은 sed표현을 가지고 있으며 , /gp각각에 대해 쓰고 싶지 않습니다 . 그것을 세계화하는 방법?
alhelal

8

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

find . -type f | xargs perl -i -ne 's/abc/def/ && print STDERR' 

변경된 줄을 표준 오류로 인쇄합니다 . 예를 들면 다음과 같습니다.

$ cat foo
fooabcbar
$ find . -type f | xargs perl -i -ne 's/abc/def/ && print STDERR' 
foodefbar

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

$ find . -type f | 
   xargs perl -i -ne '$was=$_; chomp($was);
                      s/abc/def/ && print STDERR "$ARGV($.): $was : $_"' 
./foo(1): fooabcbar : foodefbar

+1 작업중인 $ARGV파일 이름 에도 사용할 수 있습니다 .
Joseph R.

@JosephR. 좋은 지적이 추가되었습니다.
terdon

고마워, 아마 도움이 될 것입니다 (직접 테스트하지는 않았습니다). sed를 사용하지 않으므로 선택하지 않으므로 질문에 정확하게 대답하지 않습니다.
ricab

@ricab는 괜찮습니다. 실제로 질문에 대한 답변이 아니라면 대답을 수락해서는 안됩니다 . 이와 같은 간단한 것의 perl구문은의 구문과 매우 유사하며 sed귀하가 요청하는 것이 실제로 가능하다고 생각하지 않습니다 sed.
terdon

3

현재 패턴을 파일에 쓰는 w 플래그를 사용하는 것이 가능 합니다. 대체 명령에 파일을 추가하여 파일에 대한 대체 파일을보고하고 작업이 완료된 후 인쇄 할 수 있습니다. 또한 교체 된 문자열을 grep으로 채색하고 싶습니다.

sed -i -e "s/From/To/gw /tmp/sed.done" file_name
grep --color -e "To" /tmp/sed.done

w 와 파일 이름 사이에는 공백이 하나만 있어야합니다 .

diffing은 sed가 수행하지 않은 경우에도 변경 사항을 표시 할 수 있기 때문에 diff보다 낫습니다.


방금 테스트하여 sed는 하위 라인을 씁니다 sed.done. 원본 파일에서 "받는 사람"과 선은 그러므로에 인쇄되지 않습니다 sed.done당신이 경우에 따라서, grep "To" sed.done당신은 단지 라인을 볼 수 있습니다 변경을 sed. 파일 이 대체 되기 전에 파일에 원래 줄이 표시되지 않습니다. 이것이 목표로하는
것이라면

1

나는 @terdon 솔루션을 좋아합니다-펄은 이것에 좋습니다.

여기 내 조정 된 버전이 있습니다.

  • 일치하는 문자열이없는 파일을 변경하려고 시도하지 않습니다
  • 변경되는 파일의 이전 버전을 백업합니다 (.bak 버전 생성).
  • 변경된 모든 파일 / 줄을 나열하고 쉽게 읽을 수 있도록 들여 쓰기 및 그 아래에 해당 줄의 OLD 및 NEW 버전을 표시합니다

암호

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.