使用sed捕获组变量作为bash命令的输入。

时间:2022-02-11 12:28:23

I have text like: TEXT="I need to replace the hostname [[google.com]] with it's ip in side the text"

我有这样的文本:text ="我需要将主机名[google.com]替换为文本的ip "

Is there a way to use something like below, but working? sed -Ee "s/\[\[(.*)\]\]/`host -t A \1 | rev | cut -d " " -f1 | rev`/g" <<< $TEXT

是否有一种方法可以使用下面这样的东西,但是可以工作?sed ee“s / \[\[(. *)\]\]/ '主机- t \ 1 | |削减牧师- d”“f1 |的牧师/ g“< < < $文本

looks like the value of \1 is not being passed to the shell command used inside sed.

看起来\1的值没有传递给sed中使用的shell命令。

Thanks

谢谢

4 个解决方案

#1


1  

Backquote interpolation is performed by the shell, not by sed. This means that your backquotes will either be replaced by the output of a command before the sed command is run, or (if you correctly quote them) they will not be replaced at all, and sed will see the backquotes.

Backquote插值是由shell执行的,而不是sed。这意味着在运行sed命令之前,您的反引号将被命令的输出所取代,或者(如果您正确地引用它们)它们根本不会被替换,而sed将看到反引号。

You appear to be trying to have sed perform a replacement, then have the shell perform backquote interpolation.

您似乎试图让sed执行替换,然后让shell执行backquote插入。

You can get the backquotes past the shell by quoting them properly:

你可以通过适当的引用来获得外壳后面的引号:

$ echo "" | sed -e 's/^/`hostname`/'
`hostname`

However, in that case you will have to use the resulting string in a shell command line to cause backquote interpolation again.

但是,在这种情况下,您将不得不在shell命令行中使用所产生的字符串,从而再次导致反向引用。

Depending on how you feel about awk, perl, or python, I'd suggest you use one of them to do this job in a single pass. Alternatively, you could make a first pass extracting the hostnames into a command without backquotes, then execute the commands to get the IP addresses you want, then replace them in another pass.

根据您对awk、perl或python的感觉,我建议您使用其中之一在一次传递中完成这项工作。或者,您可以先将主机名提取到一个命令中,而不需要反向引用,然后执行命令来获取您想要的IP地址,然后在另一个通道中替换它们。

#2


1  

It's got to be a two part command, one to get a variable that bash can use, the other to do a straight-up /s/ replacement with sed.

必须有两个部分的命令,一个是获取bash可以使用的变量,另一个是直接执行/s/替换sed。

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)'/'

But, more cleanly using how to split a string in shell and get the last field

但是,更简洁地使用如何在shell中分割字符串并获得最后一个字段

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##* }/

The short version is that you can't mix sed and bash the way you're expecting to.

简短的版本是,您不能以预期的方式混合sed和bash。

#3


0  

This works:

如此:

#!/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

#4


0  

Thank you all,

谢谢大家,

I made the below solution:

我做了以下的解决方案:

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
 }

Where resolve_hosts gets a text file as an argument

resolve_hosts在哪里获得文本文件作为参数

#1


1  

Backquote interpolation is performed by the shell, not by sed. This means that your backquotes will either be replaced by the output of a command before the sed command is run, or (if you correctly quote them) they will not be replaced at all, and sed will see the backquotes.

Backquote插值是由shell执行的,而不是sed。这意味着在运行sed命令之前,您的反引号将被命令的输出所取代,或者(如果您正确地引用它们)它们根本不会被替换,而sed将看到反引号。

You appear to be trying to have sed perform a replacement, then have the shell perform backquote interpolation.

您似乎试图让sed执行替换,然后让shell执行backquote插入。

You can get the backquotes past the shell by quoting them properly:

你可以通过适当的引用来获得外壳后面的引号:

$ echo "" | sed -e 's/^/`hostname`/'
`hostname`

However, in that case you will have to use the resulting string in a shell command line to cause backquote interpolation again.

但是,在这种情况下,您将不得不在shell命令行中使用所产生的字符串,从而再次导致反向引用。

Depending on how you feel about awk, perl, or python, I'd suggest you use one of them to do this job in a single pass. Alternatively, you could make a first pass extracting the hostnames into a command without backquotes, then execute the commands to get the IP addresses you want, then replace them in another pass.

根据您对awk、perl或python的感觉,我建议您使用其中之一在一次传递中完成这项工作。或者,您可以先将主机名提取到一个命令中,而不需要反向引用,然后执行命令来获取您想要的IP地址,然后在另一个通道中替换它们。

#2


1  

It's got to be a two part command, one to get a variable that bash can use, the other to do a straight-up /s/ replacement with sed.

必须有两个部分的命令,一个是获取bash可以使用的变量,另一个是直接执行/s/替换sed。

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)'/'

But, more cleanly using how to split a string in shell and get the last field

但是,更简洁地使用如何在shell中分割字符串并获得最后一个字段

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##* }/

The short version is that you can't mix sed and bash the way you're expecting to.

简短的版本是,您不能以预期的方式混合sed和bash。

#3


0  

This works:

如此:

#!/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

#4


0  

Thank you all,

谢谢大家,

I made the below solution:

我做了以下的解决方案:

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
 }

Where resolve_hosts gets a text file as an argument

resolve_hosts在哪里获得文本文件作为参数