使用 Bash/Sed/Awk 在模板文件中查找变量名称?

使用 Bash/Sed/Awk 在模板文件中查找变量名称?

我有一些模板文件,目前正在使用 envsubst 进行处理,效果很好。

<?php

$config['db_host'] = '${DB_HOST}';
$config['db_port'] = '${DB_PORT}';
$config['url'] = 'http://${WEB_HOST}/${WEB_PATH}';

// Please do NOT change this value
$config['maxSize'] = 25;

我试图找到一种使用 bash 脚本扫描文件并生成需要设置的所有环境变量的列表的方法,这样我就可以将它们转储到 .env 文件中,如下所示:

DB_HOST=
DB_PORT=
WEB_HOST=
WEB_PATH=

我认为 sed 是可能的,但是我在 30 分钟的谷歌搜索后找到的所有示例都是关于如何替换内联变量,而不是关于打印出匹配项。

答案1

您的标准似乎是:匹配${和之间包含的任意数量的大写字母或下划线}

gawk可以单独使用它,或者grep可以简化模式匹配部分(但之后需要额外的格式化)。


GNU awk

gawk -v 'RS=[$]{' -F '}' '$1 ~ /^[A-Z_]+$/ && !a[$1]++ {printf "%s=\n", $1}' FILE
  • GNU awk 可以接受记录分隔符的正则表达式,因此通过分配,它将在模式出现的任何地方RS=[$]{将输入拆分为记录FILE${
  • 字段分隔符设置为}- 现在可以检查每个记录的第一个字段,看看它是否符合您的其他条件:除了一个或多个[A-Z_]
  • 使用&& !a[$1]++将删除重复项
  • =print 语句在每行末尾添加一个等号- 以匹配您所需的输出
  • 另请注意:文件的第一部分将始终被算作第一个记录 - 即使它不是以以下开头${- 这意味着如果您的文件以[A-Z_]+}(不太可能)开头 - 这些大写字母/下划线将“匹配”并被打印在输出的第一行

grep+ 格式化

grep也许更容易理解(感谢它的-o/--only-matching选项):

grep -o '${[A-Z_]\+}' FILE
  • 但这不会格式化输出:通过管道sed可以做到这一点:例如。
grep -o '${[A-Z_]\+}' FILE | sed 's/${\(.*\)}/\1=/'
  • 这不会删除重复项:通过管道输出sort -u来做到这一点,或者通过 awk 管道一次:
grep -o '${[A-Z_]\+}' FILE | awk -F '[{}]' '!a[$0]++{printf "%s=\n", $2}'

答案2

这就是我最终所做的:

cat file | grep -o '${\w*}' | sed -e 's|${||g' -e 's|}|=|g'

DB_HOST=
DB_PORT=
WEB_HOST=
WEB_PATH=

即使它不漂亮,但似乎工作得很好!

或者另一种方法(修改自https://unix.stackexchange.com/a/13467/229729):

cat file | sed -n -e 's/.*${\(\w\+\)}.*/\1=/p'

相关内容