【问题标题】:Using sed captured group variable as input for bash command使用 sed 捕获的组变量作为 bash 命令的输入
【发布时间】:2018-02-11 09:45:00
【问题描述】:
我有这样的文字:
TEXT="I need to replace the hostname [[google.com]] with it's ip in side the text"
有没有办法使用类似下面的东西,但工作?
sed -Ee "s/\[\[(.*)\]\]/`host -t A \1 | rev | cut -d " " -f1 | rev`/g" <<< $TEXT
看起来 \1 的值没有传递给 sed 中使用的 shell 命令。
谢谢
【问题讨论】:
标签:
regex
linux
string
bash
sed
【解决方案1】:
谢谢大家,
我做了以下解决方案:
function host_to_ip () {
echo $(host -t A $1 | head -n 1 | rev | cut -d" " -f1 | rev)
}
function resolve_hosts () {
local host_placeholders=$(grep -o -e "##.*##" $1)
for HOST in ${host_placeholders[@]}
do
sed -i -e "s/$HOST/$(host_to_ip $(sed -Ee 's/##(.*)##/\1/g' <<< $HOST))/g" $1
done
}
resolve_hosts 获取文本文件作为参数的地方
【解决方案2】:
这行得通:
#!/bin/bash
txt="I need to replace the hostname [[google.com]] with it's ip in side the text"
host_name=$(sed -E 's/^[^[]*\[\[//; s/^(.*)\]\].*$/\1/' <<<"$txt")
ip_addr=$(host -tA "$host_name" | sed -E 's/.* ([0-9.]*)$/\1/')
echo "$txt" | sed -E 's/\[\[.*\]\]/'"$ip_addr/"
# I need to replace the hostname 172.217.4.174 with it's ip in side the text
【解决方案3】:
它必须是一个由两部分组成的命令,一个用于获取 bash 可以使用的变量,另一个用于直接用 sed 替换 /s/。
TEXT="I need to replace the hostname [[google.com]] with it's ip in side the text"
DOMAIN=$(echo $TEXT | sed -e 's/^.*\[\[//' -e 's/\]\].*$//')
echo $TEXT | sed -e 's/\[\[.*\]\]/'$(host -tA $DOMAIN | rev | cut -d " " -f1 | rev)'/'
但是,使用how to split a string in shell and get the last field 更干净
TEXT="I need to replace the hostname [[google.com]] with it's ip in side the text"
DOMAIN=$(echo $TEXT | sed -e 's/^.*\[\[//' -e 's/\]\].*$//')
HOSTLOOKUP=$(host -tA $DOMAIN)
echo $TEXT | sed -e 's/\[\[.*\]\]/'${HOSTLOOKUP##* }/
简短的版本是您不能按照您期望的方式混合 sed 和 bash。
【解决方案4】:
反引号插值由 shell 执行, 而不是 sed。这意味着您的反引号将在 sed 命令运行之前被命令的输出替换,或者(如果您正确引用它们)它们根本不会被替换,sed 将看到反引号。
您似乎试图让 sed 执行替换,然后让 shell 执行反引号插值。
您可以通过正确引用它们来使反引号越过外壳:
$ echo "" | sed -e 's/^/`hostname`/'
`hostname`
但是,在这种情况下,您将不得不在 shell 命令行中使用生成的字符串来再次引起反引号插值。
根据您对 awk、perl 或 python 的感觉,我建议您使用其中一个来一次性完成这项工作。或者,您可以先将主机名提取到不带反引号的命令中,然后执行命令以获取所需的 IP 地址,然后在另一遍中替换它们。