Bash 解析 .env 文件的命令包含等号 (=) 登录值

Bash command to parse .env file contains equal (=) sign in values

我有一个 .env 文件,

# Some variables
USERNAME=user1
PASSWORD=

# Other variables
URL=https://example.com
TOKEN=muDm8qJ6mqM__YX024dk1RXluPnwd-3mxyt1LwLoI4ISiVPA==

目的

我的目的是创建一行bash命令以<name> <value>格式打印每个非空变量,这应该

  1. 为每个变量打印一行,名称和变量之间有 [space] 值;
  2. 忽略评论;
  3. 忽略没有值的变量;

预期输出

预期输出是,

USERNAME user1
URL https://example.com
TOKEN muDm8qJ6mqM__YX024dk1RXluPnwd-3mxyt1LwLoI4ISiVPA==

当前解决方案

我目前的解决方案如下,

grep -v '^#' .env | grep -v '^[[:space:]]*$' | grep -v '=$' | sed 's/=/ /' | while read -r line; do echo $line; done

实际产量

USERNAME user1
URL https://example.com

它只打印出前两行,最后一行的问题是由 TOKEN 值中的等号 (=) 引起的。

需要帮助

谁能帮我改一下命令?如果有更简单的方法来实现目标,也欢迎。

处理任何环境变量文件的唯一方法是实际解释它。下面介绍打印变量列表的各种方法。

各种“环境文件”通常被设计成运行被POSIXshell评估所有的变量。这使得在分配给变量时可以调用外部命令、执行计算等。

仅当您信任您的输入文件时才这样做。任何命令都可以通过使用下面的脚本解析文件来执行。

您可以获取文件(内置命令.):

. .env

获取它之后,您可以计算变量。如果您知道要打印的所有变量,请使用此(对于变量 USERNAMEPASSWORD

. .env

for var_name in USERNAME PASSWORD
do
    printf "%s %s\n" "$var_name" "${!var_name}"
done

如果要打印所有显式指定的变量,请使用此方法:

. .env

grep '^\w+=' | sed 's/=//' | while read var_name
do
    printf "%s %s\n" "$var_name" "${!var_name}"
done

但是这个解决方案也不完美,因为.env文件可以使用不同于<i>var_name</i>=[=60的结构=]value</i> 分配变量。使用set命令打印所有变量。

这会打印出 绝对所有 变量。 (实际上,环境文件应该从系统环境变量中继承它的变量,所以有很多。)

. .env
printenv | sed 's/=/ /'

sed用来去掉等号

注意一些危险的变量值。变量甚至可以包含换行符、退格符和其他控制字符。


还有许多不同的实用程序可以以允许将变量加载回 shell 的方式打印变量。例如:

declare -ptypeset -p — 打印出 declare 命令以声明所有当前设置的 shell 变量

export -p — 相同,但用于 environment 变量(这可能是您想要的)

set — 打印出所有 shell 个变量

使用sed

$ sed '/=\</!d;s/=/ /' input_file
USERNAME user1
URL https://example.com
TOKEN muDm8qJ6mqM__YX024dk1RXluPnwd-3mxyt1LwLoI4ISiVPA==

删除与有效变量不匹配的行,即在 = 之后没有输入,这也将匹配空白行,对于您的示例数据,带有注释的行,因为行中没有有效变量。最后,将第一次出现的 = 相等字符替换为 space.

如果文件只包含注释和简单的 key=value 行,字符串中没有 # 个字符,您可以使用此管道:

sed 's/#.*//' | fgrep = | sed 's/=/ /'

或者如果你不想输出空变量,使用这个:

sed 's/#.*//' | grep =. | sed 's/=/ /'