grep은 sed로 파이프하여 인라인을 대체하지만 sed가 파일 이름을 인쇄하고 줄을 변경하기를 원합니다. 가능합니까?

grep은 sed로 파이프하여 인라인을 대체하지만 sed가 파일 이름을 인쇄하고 줄을 변경하기를 원합니다. 가능합니까?

내 명령은 다음과 같습니다(의도적으로 중단됨).

grep FOO "/Users/gjtorikian/blah" -l | xargs sed -i '' '/FOO/{s/FOO/BAR/g; w /dev/stdout
}'

높은 수준에서: 디렉토리 grep의 FOO ; 인라인 교체( )를 수행하고 파일 blah이름만 -l파이프합니다 .sedsed-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

관련 정보