使用多行shell变量搜索和替换shell变量

时间:2015-01-12 23:52:06

标签: regex perl shell awk sed

我知道有很多类似的问题但是,我想由于搜索/替换变量的格式化,它们对我的情况不起作用。

我正在处理的整个脚本将读取一个文本文件(使用grep和awk的组合)来创建两个shell变量$ find和$ replace。 $ find是包含所有字符的单行字符串。 $ replace是一个包含各种字符的多行字符串。

示例:

echo "$find"

返回

type result input1 another_input random_input<10> / name

echo "$replace"

返回

.TAG name
result input1 random_input / name1
random_input<10> input1 another_input / name2
.NTAG

现在我只需用$ replace替换$ find。我尝试过sed和perl但它失败了。

尝试过(在许多其他事情中)

perl -e -i.bak "s/$find/$replace/g" text.file
perl -e -i.bak 's,"'$find'","'$replace'",g' text.file
perl -e -i.bak "s|$find|$replace|g" text.file

sed -i "s/$find/$replace/g" text.file

我的猜测是问题是由字符串中的某些字符被解释为特殊字符引起的。

感谢任何帮助!

3 个答案:

答案 0 :(得分:2)

这适用于任何查找或替换值:

$ cat file
foo
type result input1 another_input random_input<10> / name
bar

$ awk -v find="$find" -v replace="$replace" 's=index($0,find){$0=substr($0,1,s-1) replace substr($0,s+length(find))}1' file
foo
.TAG name
result input1 random_input / name1
random_input<10> input1 another_input / name2
.NTAG
bar

如果find总是一行,则可以简化,例如这可能是你所需要的:

$ awk -v find="$find" -v replace="$replace" '$0==find{$0=replace}1' file
foo
.TAG name
result input1 random_input / name1
random_input<10> input1 another_input / name2
.NTAG
bar

答案 1 :(得分:0)

将您的变量重组为

replace=".TAG name\nresult input1 random_input / name1\nrandom_input<10> input1 another_input / name2\n.NTAG"

或像这样重组

replace='.TAG name\
    result input1 random_input / name1\
    random_input<10> input1 another_input / name2\
    .NTAG'

此外,您的分隔符与变量replace字符发生冲突,因为变量中有/

您可以尝试使用#作为分隔符或任何其他不在变量中的字符

 sed "s#$find#$replace#g" text_file

答案 2 :(得分:0)

一种方式用sed,快速和脏,所以不像@Ed Morton的awk那样的防弹

find_sed="$( printf "%s" "${find}" | sed 's/[^0-9(){}]/\\&/g' )"
replace_sed="$( printf "%s" "${replace}" | sed "s/[&\\]/\\/g;s/\n/\\&/g' )"

sed "s/${find_sed}/${replace_sed}/g" YourFile
  • 可以是一行内部替换而不是变量,但更明确,如此
  • posix版本(--posix与GNU sed),如果不是posix,则根据您使用转义字符的特殊字符调整[^0-9(){}],以获取\+\n\d\
  • 等特殊含义