내 명령 (의도적 인 중단) :
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
로만 유지하는 것이 좋습니다. 두 번째 ?
댓글
답변
한 가지 가능성은 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
''
가 기본값이 아닙니다. .