내 명령 (의도적 인 중단) :

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

높은 -level : grep blah 디렉토리의 FOO, 파일 이름 만 파이프 (-l) to 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로만 유지하는 것이 좋습니다. 두 번째 ?

댓글

  • 나는 ' sed에서 현재 파일 이름을 가져 오므로 두 번째 grep이 필요할 수 있습니다.
  • 또한 ' , '가 기본값입니다.
  • OS X에서는 ''가 기본값이 아닙니다. .

답변

한 가지 가능성은 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  

답변

그대로 영어 원어민이 아니라면 아마 이해하지 못했을 것입니다.

디렉토리를 “grep”하려면 “-r”이 필요합니다. “-l”을 사용하면 파일 이름 만 인쇄되고 처음 발생한 후에는 grepping이 중지됩니다.

# 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 

Answer

한 번에 문제를 너무 복잡하게 만드는 것 같습니다.

grep -H -n /Users/gjtorikian/blah | sed "s/\(^.*?:[0-9]+?:\).*FOO.*/\1BAZ/" 

줄 번호 및 대체 파일 목록을 가져옵니다 (파일 이름에 콜론이 포함되지 않는 한 작동하지만 Mac OS에서는 나쁜 생각입니다 …). 나중에 다음을 실행할 수 있습니다.

sed -i "" "s/FOO/BAR/g" /Users/gjtorikian/blah 

여기에는 grep 및 xarg가 필요하지 않습니다 (파일이 많은 경우 “find … | xarg”를 수행 할 수 있습니다). 중복에 대해 두 줄을 스크립트 또는 함수에 넣고 거기에서 변수 대체를 수행 할 수 있습니다.

코멘트

  • sed -i ...는 스트림이 변경되지 않아도 파일 시간을 변경합니다.
  • @jww : 당신 ' 맞습니다. '는 는 파일 편집기가 아닌 스트림 편집기이므로 -i 옵션은 유닉스 철학을 위반합니다 ( mywiki.wooledge .org / BashFAQ / 021 # Using_nonstandard_tools ). 이를 방지하려면 ex (예 : ex -sc '%s/FOO/BAR/ge|x' /Users/gjtorikian/blah)를 사용하세요.

답변

현재 디렉토리 (자동 모드)에서 FOO를 BAR로 재귀 적으로 대체

grep -rl "FOO" | xargs sed -i "s/FOO/BAR/" 

답변

1 라이너

grep -n FOO * -R|awk -F\: "{ print $1 }"|sort|uniq|while read file; do sed -i "s/FOO/BAR/g" $file; done 

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다