이 OSX/BSD/GNU sed 해결 방법이 작동하지 않는 이유

이 OSX/BSD/GNU sed 해결 방법이 작동하지 않는 이유

따라서 sed는 OSX/BSD 버전인지 GNU 버전인지에 따라 다르게 동작합니다.

OSX에는 다음이 필요합니다.

sed -i '' <pattern> <file>

그리고 이것은 GNU sed에서 작동합니다:

sed -i <pattern> <file>

그래서 나는 이것을 가지고 있습니다 :

darwin=false;
case "$(uname)" in
    Darwin*) darwin=true ;;
esac

if $darwin; then
    sedi="sed -i '' "
else
    sedi="sed -i"
fi

그런 다음 OSX에서 호출하려고합니다.

$sedi "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

"Version.java"라는 백업 파일을 생성하는 것을 제외하고는 잘 작동합니다.

CLI에서 명시적으로 이 작업을 수행하면 다음과 같이 작동하지 않는 이유가 무엇인지 잘 모르겠습니다.

sed -i '' "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

백업 파일을 만들지 않고도 작동합니다.

어떤 아이디어가 있나요?

답변1

sedi변수를 확장하면 ''예상대로 빈 매개변수를 생성하는 대신 변수가 매개변수로 전달됩니다.sed

내가 볼 수 있는 가장 좋은 방법은 sedi변수를 배열로 만드는 것입니다.

if $darwin; then
    sedi=(sed -i '')
else
    sedi=(sed -i)
fi

다음과 같이 사용하십시오 :

"${sedi[@]}" "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

그렇지 않은 경우 매개변수를 실제 빈 매개변수로 바꾸는 유일한 방법은 ''원래 선언을 사용하는 것입니다.eval

eval $sedi '"s/VERSION =.*;/VERSION = \"${lver}\";/g"' Version.java

그러나 이는 명령의 나머지 부분에 인용/이스케이프 레이어를 추가해야 하기 때문에 다소 성가신 솔루션입니다. 또한 eval가능하면 이를 피하는 것이 일반적으로 좋은(그리고 안전한) 습관입니다.

고쳐 쓰다

아래 설명대로 함수를 생성하면 됩니다. 같은 트랙에서 an은 alias아마도 가장 짧은 방법일 것입니다.

if $darwin; then
    alias sedi="sed -i ''"
else
    alias sedi="sed -i"
fi

사용이 간편함:

sedi "s/VERSION =.*;/VERSION = \"${lver}\";/g" Version.java

답변2

개행 쉘 함수를 정의하십시오 sed.

case "$(uname)" in
    Darwin*) sed () { command sed -i '' "$@"; } ;;
    *)       sed () { command sed -i "$@"; } ;;
esac

관련 정보