如何使用 sed 将标签大括号字符串替换为环境变量
How to replace a hashtag curly bracket string with an environment variable by using sed
我一直在尝试编写一个 bash 脚本,该脚本可以在目录中递归搜索并替换多个字符串,例如#{DEMO_STRING_1}
等带有环境变量,例如$sample1
.
完整脚本:
#!/bin/sh
find /my/path/here -type f -name '*.js' -exec sed -i \
-e 's/#{DEMO_STRING_1}/'"$sample1"'/g' \
-e 's/#{DEMO_STRING_2}/'"$sample2"'/g' \
-e 's/#{DEMO_STRING_3}/'"$sample3"'/g' \
-e 's/#{DEMO_STRING_4}/'"$sample4"'/g' \
-e 's/#{DEMO_STRING_5}/'"$sample5"'/g' \
-e 's/#{DEMO_STRING_6}/'"$sample6"'/g' \
-e 's/#{DEMO_STRING_7}/'"$sample7"'/g' \
-e 's/#{DEMO_STRING_8}/'"$sample8"'/g' \
{} +
我不知道如何用带有大括号的主题标签替换字符串。
我试过这个例子:sed find and replace with curly braces or Environment variable substitution in sed但我不知道如何组合它们。
我错过了什么?我还搜索了需要转义的字符,例如What characters do I need to escape when using sed in a sh script? 但同样不是我需要的字符。
特定格式抛出以下错误:
sed: bad option in substitution expression
我哪里错了?
更新:环境变量示例:
- https://www.example.com
- /示例字符串/
- 12345-abcd-54321-efgh
- base64 字符串
以上情况都是我要替换的环境变量。所有环境变量都在双引号内。
重要的是要了解环境变量引用是由 shell 扩展的,因为它准备执行命令,而不是命令本身(在本例中为 sed
)。该命令只能看到展开的结果。
在您的情况下,这意味着如果任何环境变量的值包含在上下文中对 sed
有意义的字符,例如未转义的(对 sed
)斜杠(/
), 那么 sed
将赋予它们特殊的意义,而不是将它们解释为普通字符。例如,给定一个 sed
命令,如
sed -e "s/X/${var}/" <<EOF
Replacement: X
EOF
,如果 $var
的值为 Y
那么输出将是
Replacement: Y
,但如果 $var
的值为 /path/to/Y
,则 sed
将失败并出现与您报告的相同的错误。发生这种情况是因为 sed
命令实际上 运行 与您输入的
相同
sed -e s/X//path/to/Y
,其中包含无效的 s
指令。可能最好的选择是转义 replacement-string 字符,否则这些字符对 sed
很重要。您可以通过插入 shell 函数来做到这一点:
escape_replacement() {
# replace all \ characters in the first argument with double backslashes.
# Note that in order to do that here, we need to escape them from the shell
local temp=${1//\/\\}
# Replace all & characters with \&
temp=${temp//&/\&}
# Replace all / characters with \/, and write the result to standard out.
# Use printf instead of echo to avoid edge cases in which the value to print
# is interpreted to be or start with an option.
printf -- "%s" "${temp//\//\/}"
}
然后脚本会像这样使用它:
find /my/path/here -type f -name '*.js' -exec sed -i \
-e 's/#{DEMO_STRING_1}/'"$(escape_replacement "$sample1")"'/g' \
...
请注意,您可能还想使用一个 shebang 行来明确指定支持替换引用 (${parameter/pattern/replacement}
) 的 shell,因为 POSIX 不需要这些,并且您可能 运行 进入一个 /bin/sh
是不支持它们的 shell 的系统。如果您愿意依赖 Bash 那么这应该反映在您的 shebang 行中。或者,您可以准备一个不依赖替换引用的 escape_replacement
函数版本。
如果您使用 perl
- 您不需要转义任何内容。
使用您的 shell 变量 exported 您可以通过 perl 中的 $ENV{name}
访问它。
示例:
samples=(
https://www.example.com
'/sample string/'
12345-abcd-54321-efgh
'base64 string'
$'multi\nline'
)
for sample in "${samples[@]}"
do
echo '---'
export sample
echo 'A B #{DEMO_STRING_1} C' |
perl -pe 's/#{DEMO_STRING_1}/$ENV{sample}/g'
done
echo '---'
输出:
---
A B https://www.example.com C
---
A B /sample string/ C
---
A B 12345-abcd-54321-efgh C
---
A B base64 string C
---
A B multi
line C
---
要添加 -i
选项,您可以:perl -pi -e 's///'
我一直在尝试编写一个 bash 脚本,该脚本可以在目录中递归搜索并替换多个字符串,例如#{DEMO_STRING_1}
等带有环境变量,例如$sample1
.
完整脚本:
#!/bin/sh
find /my/path/here -type f -name '*.js' -exec sed -i \
-e 's/#{DEMO_STRING_1}/'"$sample1"'/g' \
-e 's/#{DEMO_STRING_2}/'"$sample2"'/g' \
-e 's/#{DEMO_STRING_3}/'"$sample3"'/g' \
-e 's/#{DEMO_STRING_4}/'"$sample4"'/g' \
-e 's/#{DEMO_STRING_5}/'"$sample5"'/g' \
-e 's/#{DEMO_STRING_6}/'"$sample6"'/g' \
-e 's/#{DEMO_STRING_7}/'"$sample7"'/g' \
-e 's/#{DEMO_STRING_8}/'"$sample8"'/g' \
{} +
我不知道如何用带有大括号的主题标签替换字符串。
我试过这个例子:sed find and replace with curly braces or Environment variable substitution in sed但我不知道如何组合它们。
我错过了什么?我还搜索了需要转义的字符,例如What characters do I need to escape when using sed in a sh script? 但同样不是我需要的字符。
特定格式抛出以下错误:
sed: bad option in substitution expression
我哪里错了?
更新:环境变量示例:
- https://www.example.com
- /示例字符串/
- 12345-abcd-54321-efgh
- base64 字符串
以上情况都是我要替换的环境变量。所有环境变量都在双引号内。
重要的是要了解环境变量引用是由 shell 扩展的,因为它准备执行命令,而不是命令本身(在本例中为 sed
)。该命令只能看到展开的结果。
在您的情况下,这意味着如果任何环境变量的值包含在上下文中对 sed
有意义的字符,例如未转义的(对 sed
)斜杠(/
), 那么 sed
将赋予它们特殊的意义,而不是将它们解释为普通字符。例如,给定一个 sed
命令,如
sed -e "s/X/${var}/" <<EOF
Replacement: X
EOF
,如果 $var
的值为 Y
那么输出将是
Replacement: Y
,但如果 $var
的值为 /path/to/Y
,则 sed
将失败并出现与您报告的相同的错误。发生这种情况是因为 sed
命令实际上 运行 与您输入的
sed -e s/X//path/to/Y
,其中包含无效的 s
指令。可能最好的选择是转义 replacement-string 字符,否则这些字符对 sed
很重要。您可以通过插入 shell 函数来做到这一点:
escape_replacement() {
# replace all \ characters in the first argument with double backslashes.
# Note that in order to do that here, we need to escape them from the shell
local temp=${1//\/\\}
# Replace all & characters with \&
temp=${temp//&/\&}
# Replace all / characters with \/, and write the result to standard out.
# Use printf instead of echo to avoid edge cases in which the value to print
# is interpreted to be or start with an option.
printf -- "%s" "${temp//\//\/}"
}
然后脚本会像这样使用它:
find /my/path/here -type f -name '*.js' -exec sed -i \
-e 's/#{DEMO_STRING_1}/'"$(escape_replacement "$sample1")"'/g' \
...
请注意,您可能还想使用一个 shebang 行来明确指定支持替换引用 (${parameter/pattern/replacement}
) 的 shell,因为 POSIX 不需要这些,并且您可能 运行 进入一个 /bin/sh
是不支持它们的 shell 的系统。如果您愿意依赖 Bash 那么这应该反映在您的 shebang 行中。或者,您可以准备一个不依赖替换引用的 escape_replacement
函数版本。
如果您使用 perl
- 您不需要转义任何内容。
使用您的 shell 变量 exported 您可以通过 perl 中的 $ENV{name}
访问它。
示例:
samples=(
https://www.example.com
'/sample string/'
12345-abcd-54321-efgh
'base64 string'
$'multi\nline'
)
for sample in "${samples[@]}"
do
echo '---'
export sample
echo 'A B #{DEMO_STRING_1} C' |
perl -pe 's/#{DEMO_STRING_1}/$ENV{sample}/g'
done
echo '---'
输出:
---
A B https://www.example.com C
---
A B /sample string/ C
---
A B 12345-abcd-54321-efgh C
---
A B base64 string C
---
A B multi
line C
---
要添加 -i
选项,您可以:perl -pi -e 's///'