개행 문자가 포함된 환경 변수를 어떻게 설정합니까?

개행 문자가 포함된 환경 변수를 어떻게 설정합니까?

환경 변수에 RSA 키를 개행 문자가 포함된 텍스트 파일로 설정하려고 합니다.

파일에서 읽고 이를 환경 변수에 전달하려고 할 때마다 첫 번째 줄의 개행 문자에서 중지됩니다. 이런 일이 발생하지 않도록 하려면 어떻게 해야 합니까?

답변1

zsh를 제외하고 쉘 변수는 임의의 바이트 시퀀스를 저장할 수 없습니다. 다른 모든 쉘의 변수는 NUL 바이트를 포함할 수 없습니다. 의 경우 yash유효한 문자를 형성하지 않는 바이트를 포함할 수 없습니다.

NUL 바이트를 포함하지 않는 파일의 경우 POSIX와 유사한 셸에서 다음을 수행할 수 있습니다.

var=$(cat file; echo .); var=${var%.}

모든 후행 줄 바꿈이 제거된다는 사실을 설명하기 위해 .\n후행을 추가 하고 제거합니다..$(...)

위의 방법은 zshNUL이 포함된 파일에도 작동하지만 특수 연관 배열을 zsh사용할 수도 있습니다 .$mapfile

zmodload zsh/mapfile
var=$mapfile[file]

zsh 또는 bash에서는 다음을 사용할 수도 있습니다.

{ IFS= read -rd '' var || :; } < file

최대 첫 번째 NUL 바이트를 읽습니다. NUL 바이트가 발견되지 않으면 0이 아닌 종료 상태를 반환합니다. 여기에서 명령 그룹을 사용하면 최소한 파일을 열 때 오류를 알 수 있지만 종료 상태를 통해 읽기 오류를 감지할 수는 없습니다.

다른 명령에 전달할 때 이 변수를 인용하는 것을 잊지 마십시오. Newline이 기본값이므로 $IFSzsh 외부의 POSIX 유사 셸에서 목록 컨텍스트에서 이를 인용 해제하면 변수 내용이 분할됩니다( $IFS다른 문자나 와일드카드와 관련된 다른 문제는 말할 것도 없습니다).

그래서:

printf %s "$var"

예를 들어 (아니요 , 물론 그렇지 않습니다. 그러면 printf %s $varSplit+glob에 echo $var문제가 추가됩니다 ).echo


비 POSIX 쉘의 경우:

본 쉘:

Bourne 쉘은 양식 $(...)이나 ${var%pattern}연산자를 지원하지 않으므로 구현하기가 어렵습니다. 한 가지 방법은 다음을 사용 eval하고 인용하는 것입니다.

eval "var='`printf \\' | cat file - | awk -v RS=\\' -v ORS= -v b='\\\\' '
  NR > 1 {print RS b RS RS}; {print}; END {print RS}'`"

그러면 (t)csh상황은 더욱 악화됩니다. 보세요거기.

를 사용하면 빈 구분 기호 목록이 있는 명령 대체 형식을 rc사용할 수 있습니다 .``(separator){...}

var = ``(){cat file}

답변2

이를 달성하는 한 가지 방법(case 포함 0x0)은 바이너리 데이터를 쉘 변수에 인코딩된 형식으로 저장하는 것입니다.

이를 위해 Base64 인코딩을 사용할 수 있습니다(RFC 4648 참조).

예를 들어:

encoded_binary="$( cat binary | base64 -w 0 )"

이는 -w 0미적으로 매우 만족스럽습니다(약간의 메모리를 절약합니다).

바이너리 데이터를 사용하려면 다시 디코딩한 후 파이핑이나 리디렉션을 통해서만 수행할 수 있습니다.

예를 들어:

{
        printf '%s\n' "${passphrase}"
        printf '%s' "${encoded_binary}" | base64 -d
} | \
gpg --quiet --batch --passphrase-fd 0 --output - --decrypt

이 예에서 바이너리는 gpg를 사용하여 해독되는 OpenPGP 메시지입니다.

base64/ uuencode( uudecodePOSIX에서 지정)을 대신 사용할 수 있습니다.

encoded_binary="$( uuencode -m '/dev/stdout' )"
...
printf '%s' "${encoded_binary}" | uudecode -o '/dev/stdout' 

그러나 이는 /dev/stdout특수 기호(파일이 아님)여야 합니다. uudecode의 일부 구현에서는 이 기능을 올바르게 지원하지만(예: GNU) 다른 구현에서는 그렇지 않습니다(예: BusyBox'는 커밋되어 c7b90dc4d10ccc4f95940f42676ff907cee73272있고 특정 특수 빌드 옵션이 설정된 경우에만 지원합니다).

또한 다음과 같은 구조가 있는 경우:

encoded_binary="$(read_function | base64 -w 0)"

read_functionPOSIX Shell 명령 언어에서는 직접적으로 가능하지 않지만 다음과 같은 것을 사용하여 간접적으로 수행할 수 있는 종료 상태(또는 디코딩 시 동일)를 확인하고 싶을 수도 있습니다.이것.

답변3

를 사용하는 경우 zsh다음과 같이 파일 내용을 할당할 수 있습니다.

p="`cat file_to_be_read`"

답변4

매개변수 조작 체계를 지원하지 않는 전통적인 Bourne 쉘에서는 다음을 수행할 수 있습니다.

NL='
'
var=`cat file`
while case `printf '%s\n' "$var" | wc -l` in "`wc -l < file`" ) break ;; esac
do var=$var$NL; done

처음에는 file이라는 파일의 내용부터 시작합니다. 이제 후행 줄 바꿈이 있는 경우에만 루프가 시작됩니다 while. 후행이 아닌 개행 문자에는 명령 대체가 건드리지 않기 때문에 아무런 문제가 없습니다.

while 루프가 반복될 때마다 개행 문자가 변수에 연결되며 여기에는 sub (일명) 명령이 포함되지 않으므로 ...개행 손실이 발생하지 않습니다.

관련 정보