如何设置包含换行符的环境变量?

如何设置包含换行符的环境变量?

我正在尝试将 RSA 密钥设置为环境变量,该环境变量作为文本文件包含换行符。

每当我尝试从文件中读取并将其传递到环境变量中时,它都会停在第一行的换行符处。我怎样才能防止这种情况发生?

答案1

请注意,除了 zsh 之外,shell 变量不能存储任意字节序列。所有其他 shell 中的变量不能包含 NUL 字节。对于yash,它们不能包含不形成有效字符的字节。

对于不包含 NUL 字节的文件,在类似 POSIX 的 shell 中,您可以执行以下操作:

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

我们添加 a.\n并删除尾随.以解决$(...)删除所有尾随换行符的事实。

上面的方法也适用zsh于包含 NUL 的文件,尽管zsh您也可以使用$mapfile特殊的关联数组:

zmodload zsh/mapfile
var=$mapfile[file]

在 zsh 或 bash 中,您还可以使用:

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

最多读取第一个 NUL 字节。除非找到 NUL 字节,否则它将返回非零退出状态。我们在这里使用命令组至少能够告诉打开文件时的错误,但我们无法通过退出状态检测读取错误。

请记住在传递给其他命令时引用该变量。 Newline 是 的默认值$IFS,因此在 zsh 之外的类 POSIX shell 的列表上下文中不加引号时会导致变量内容被分割(更不用说其他字符$IFS或通配符的其他问题)。

所以:

printf %s "$var"

例如(不是printf %s $var,当然不是,除了 split+glob 之外,echo $var这还会增加的问题)。echo


对于非 POSIX shell:

伯恩外壳:

bourne shell 不支持表单$(...)也不${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

实现此目的的一种方法(包括 的情况0x0)是将任何二进制数据以编码形式存储在 shell 变量中。

为此,可以使用 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可以使用/ uuencodeuudecode由 POSIX 指定)来代替。

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_function(或解码时相同),这在 POSIX Shell 命令语言中不能直接实现,但可以间接使用诸如

答案3

如果您使用zsh,您可以像这样分配文件的内容:

p="`cat file_to_be_read`"

答案4

在不支持参数操作方案的传统 bourne shell 上,我们可能会执行以下操作:

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(又名 )...,因此不会发生换行符丢失。

相关内容