使用Shell脚本替换文件中的令牌

Dec*_*ius 1 linux bash shell awk sed

我有一个保存令牌变量的文件。当我们切换环境时,我们想为我们所处的环境正确替换那些令牌。

如何在Linux Shell中执行此操作?我在想awk或sed。

例:

文件具有以下数据:

DB_HOST=__HOST__
DB_PASSWORD=__PASSWORD__
Run Code Online (Sandbox Code Playgroud)

我想阅读此文件,识别__HOST__并将其替换为环境变量$(HOST)。我们将从两个下划线之间的匹配字符串中获取环境变量名称。

有谁知道我们如何做到这一点?

ric*_*ici 6

该程序envsubst是专为此目的而设计的,但它希望对从环境中替换的字符串使用标准的外壳格式:

# Here-doc delimiter quoted to avoid having the shell do the substitutions
$ HOST=myhost PASSWORD=secret envsubst <<"EOF"
DB_HOST=$HOST
DB_PASSWORD=${PASSWORD}
EOF

DB_HOST=myhost
DB_PASSWORD=secret
Run Code Online (Sandbox Code Playgroud)

envsubst是Gnu gettext的一部分,并且可以广泛使用。如果确实需要使用__...__语法,则可以envsubst通过sed管道将其更改为语法很容易:

$ cat myfile.txt
DB_HOST=__HOST__
DB_PASSWORD=__PASSWORD__

$ sed -E 's/__(([^_]|_[^_])*)__/${\1}/g' myfile.txt |envsubst
Run Code Online (Sandbox Code Playgroud)

或者,如果您拥有Python,则有一个非常简单的解决方案:

from sys import stdin
from os import getenv
import re

pattern = re.compile(r"__(\w*)__")

def replacer(m):
    val = getenv(m[1])
    if val is None:
        # No such environment
        # Perhaps produce a warning, or an error
        # Here we just pass through the string unaltered
        return m[0]
    return val

print(pattern.sub(replacer, stdin.read()))
Run Code Online (Sandbox Code Playgroud)

例:

$ export HOST=myhost PASSWORD=secret 
$ python3 subst.py < myfile.txt
DB_HOST=myhost
DB_PASSWORD=secret
Run Code Online (Sandbox Code Playgroud)

该解决方案的关键是Python(不幸的是,只有少数几种其他语言)允许将模式替换的replace参数用作一个函数,然后在每个连续的匹配项上调用该模式以生成替换文本。这使得在Python中编写这样的函数比在awk中更容易,例如在固定替换文本的地方。


tha*_*guy 5

这是什么m4意思:

$ export HOST=myhost PASSWORD=mypassword

$ cat myfile
DB_HOST=__HOST__
DB_PASSWORD=__PASSWORD__

$ m4 -D __HOST__="$HOST" -D __PASSWORD__="$PASSWORD" myfile
DB_HOST=myhost
DB_PASSWORD=mypassword
Run Code Online (Sandbox Code Playgroud)

如果你想为所有环境变量自动定义宏,如果有点不确定,当然是可能的:

$ export HOST=myhost PASSWORD=mypassword

$ cat myfile
DB_HOST=__HOST__
DB_PASSWORD=__PASSWORD__

$ m4 -D __HOST__="$HOST" -D __PASSWORD__="$PASSWORD" myfile
DB_HOST=myhost
DB_PASSWORD=mypassword
Run Code Online (Sandbox Code Playgroud)

它不一定是最简单的方法,但它非常灵活和可扩展,支持条件语句、宏函数等。

  • *认为自己“m4”?那是什么?* 这正是我喜欢这个网站的地方,因为这是真的——你真的每天都能学到新东西。+1 (3认同)