내 명령은 다음과 같습니다(의도적으로 중단됨).
grep FOO "/Users/gjtorikian/blah" -l | xargs sed -i '' '/FOO/{s/FOO/BAR/g; w /dev/stdout
}'
높은 수준에서: 디렉토리 grep
의 FOO ; 인라인 교체( )를 수행하고 파일 blah
이름만 -l
파이프합니다 .sed
sed
-i ''
변경된 용어만도착하다 /dev/stdout
.
-l
및 파이프를 생략하면 다음에서 이를 얻을 수 있습니다 grep
.
/Users/gjtorikian/blah/baz.cs:1:FOO
/Users/gjtorikian/blah/bar.js:1:FOO
내가 원하는 것은 sed
인라인 대체를 수행한 다음 대체된 파일과 용어를 표시하는 것입니다.
/Users/gjtorikian/blah/baz.cs:1:BAR
/Users/gjtorikian/blah/bar.js:1:BAR
그런 일이 가능합니까? 나는 차라리 그것을 갖고 싶습니다 grep
/ 그것이 중요하다면 sed
. grep
잠시 후에 해야 합니까 sed
?
답변1
grep
한 가지 가능성은 의 출력을 전달하는 것입니다 sed
.
grep -l FOO "/Users/gjtorikian/blah/"* |
{ tee /dev/fd/3 |
xargs sed -i -e '/FOO/{' -e 's/FOO/BAR/g' -e 'w /dev/stdout'
} 3>&1 | sed 's/:FOO$/:BAR/'
일치하는 항목이 발견되면 sed
명령을 사용하여 줄 번호를 인쇄하고 추가 후처리를 수행할 수 있습니다.=
awk를 사용하면 더 명확해질 수 있습니다.
for x in "/Users/gjtorikian/blah/"*; do
awk '
sub(/FOO/, "BAR") {found=1; print FILENAME ":" NR ":" "BAR" >"/dev/stderr"}
1 {print}
END {exit(!found)}
' "$x" >"$x.tmp" && mv "$x.tmp" "$x"
done
답변2
제 모국어가 영어가 아니기 때문에 이해하지 못할 수도 있습니다.
디렉토리를 "grep"하려면 "-r"이 필요합니다. 파일 이름만 인쇄하고 첫 번째 발생 후 grep을 중지하려면 "-l"을 사용하십시오.
# pattern=/home ; grep -l "$pattern" /etc/[a-z]* 2>/dev/null | while read line ; do echo "$line:$pattern" ; done
/etc/adduser.conf:/home
/etc/fstab:/home
/etc/fstab~:/home
/etc/libuser.conf:/home
/etc/mpd.conf:/home
/etc/mpd.conf~:/home
/etc/mtab:/home
/etc/netscsid.conf:/home
/etc/passwd:/home
/etc/passwd-:/home
/etc/sudoers:/home
/etc/sudoers.tmp~:/home
답변3
현재 디렉터리에서 FOO를 BAR로 반복적으로 교체합니다(자동 모드).
grep -rl 'FOO' | xargs sed -i 's/FOO/BAR/'
답변4
짧막 한 농담
grep -n FOO * -R|awk -F\: '{ print $1 }'|sort|uniq|while read file; do sed -i 's/FOO/BAR/g' $file; done