변수와 따옴표를 사용하도록 sed를 얻을 수 없습니다

변수와 따옴표를 사용하도록 sed를 얻을 수 없습니다

이 줄을 대체하기 위해 쉘 스크립트를 작성하겠습니다.

exec "$progdir/$program" ${1+"$@"}

그리고:

exec qemu-arm -L /mnt/c/git/build/linux_arm7/build_arm7/sysroot "$progdir/$program" ${1+"$@"}

파일에서. /mnt/c/git/build/linux_arm7/build_arm7이제 이라는 변수에 위치합니다 BUILD_DIRECTORY. 내가 무엇을 시도하든(따옴표, 다른 구분 기호) 항상 대체 대신 변수로 끝납니다. 예를 들어 나는 이것을 시도했다:

#!/bin/bash
sed_test()
{
    sed -i 's|exec "\$progdir\/\$program" \${1+"\$@"}|exec qemu-arm -L ${BUILD_DIRECTORY}\/sysroot "\$progdir\/\$program" \${1+"\$@"}|g' ${BUILD_DIRECTORY}/file
}

파일에 이것을 얻었습니다 :

exec qemu-arm -L ${BUILD_DIRECTORY}/sysroot "$progdir/$program" ${1+"$@"}

이를 올바르게 수행하는 방법은 무엇입니까?

답변1

  • ${BUILD_DIRECTORY}참조로 인해 변수 확장이 방지됨
  • g최종 필요없음
  • 넌 너무 많이 탈출했어

BUILD_DIRECTORY 변수에 공백이 없으면 다음을 사용하십시오.

sed -i 's|exec "$progdir/$program" ${1+"$@"}|exec qemu-arm -L '${BUILD_DIRECTORY}'/sysroot "$progdir/$program" ${1+"$@"}|'  ${BUILD_DIRECTORY}/file

주변의 작은따옴표에 유의하세요.${BUILD_DIRECTORY}

BUILD_DIRECTORY에 공백이 있는 경우(예 linux arm7: ) 릴레이 문자열을 사용합니다(명령 분할).

sed -e 's|exec "$progdir/$program" ${1+"$@"}|exec qemu-arm -L BUILD_DIRECTORY/sysroot "$progdir/$program" ${1+"$@"}|'  
   -e "s|BUILD_DIRECTORY|${BUILD_DIRECTORY}|" 
   "${BUILD_DIRECTORY}/file"

생산하다

exec qemu-arm -L /mnt/c/git/build/linux arm7/build_arm7/sysroot "$progdir/$program" ${1+"$@"}

답변2

그리고 :zshperl

SRC='exec "$progdir/$program" ${1+"$@"}' \
  DST='exec qemu-arm -L '${(qq)BUILD_DIRECTORY}' "$progdir/$program" ${1+"$@"}' \
  perl -pi -e 's/\Q$ENV{SRC}\E/$ENV{DST}/g' -- "$BUILD_DIRECTORY/file"

Bourne과 같은 쉘 코드를 편집하고 있으므로 결과가 유효한 쉘 코드인지 확인해야 합니다. 따라서 , , , 공백 과 같은 쉘 구문의 특수 문자가 포함되어 있어도 결과를 구문 분석할 때 해당 값이 인수로 전달되는 $BUILD_DIRECTORY방식으로 변수의 내용을 삽입 해야 합니다 . .shqemu-arm;?'

가장 좋은 방법은 가장 안전한 인용 모드인 작은따옴표로 표현하는 것이며 sh, 변수에 작은따옴표 문자가 포함되어 있는 경우 \'작은따옴표 바깥에 삽입하세요. 이것이 qq매개변수 확장 플래그의 역할입니다 zsh. 예를 들어 다음과 같습니다.

  • 빈 문자열을 넣습니다.''
  • a;b입력하다'a;b'
  • a'b입력하다'a'\''b'

$BUID_DIRECTORY전달된 코드 내부의 값을 확장하면 해당 컨텍스트에서 특수 문자를 이스케이프 처리하지 않는 한 sed코드 주입 취약점이 발생한다는 의미입니다 . sed또한 -i( sed참조에서 복사한 일부 구현 perl)은 표준이 아닙니다.

대신 사용하는 것은 perl다음을 의미합니다.

  • -i휴대용으로 사용하시면 됩니다
  • /를 $SRC사용하여 이스케이프할 수 있으므로 정규식 연산자를 이스케이프할 필요가 없습니다 .\Q\E
  • 대체를 피할 필요도 없습니다.

답변3

sed 코드를 삽입하기 위해 변수를 사용하는 방법은 s///명령의 LHS 또는 RHS에서 사용되는지 여부에 따라 먼저 쉘 검증 가능한 콘텐츠를 이스케이프하는 것입니다.

& \ and :귀하의 시나리오에서는 빌드 변수가 rhs에 배치됩니다. 따라서 실제 sed 코드에서는 구분 기호로 사용하므로 문자를 이스케이프해야 합니다 s:::. 또한 빌드 변수가 여러 줄이면 줄 바꿈도 이스케이프됩니다. 변수는 작은따옴표로 묶여 있으므로 '\''빌드 변수에 작은따옴표가 있는 경우 모든 작은따옴표도 변경해야 합니다.

BUILD_DIRECTORY='/mnt/c/git/build/linux_arm7/build_arm7'

BUILD_DIRECTORY_rhs=$(printf '%s\n' "${BUILD_DIRECTORY}" |
sed \
  -e 's/[\&:]/\\&/g'    \
  -e 's/'\''/&\\\\&&/g' \
  -e '$!s/$/\\/')

sed -i -e 's:^exec \("$progdir/$program" ${1+"$@"}\)$:'"exec qemu-arm -L '${BUILD_DIRECTORY_rhs}/sysroot' \\1:"  -- "${BUILD_DIRECTORY}/file"

이 출력은 다음과 같습니다.

exec qemu-arm -L '/mnt/c/git/build/linux_arm7/build_arm7/sysroot' "$progdir/$program" ${1+"$@"}

관련 정보