搜索并用多行 shell 变量替换 shell 变量

Search and replace shell variable with multiline shell variable

我知道有很多类似的问题,但我猜是因为 search/replace 变量的格式,它们不适用于我的情况。

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

示例:

echo "$find"

returns

type result input1 another_input random_input<10> / name

echo "$replace"

returns

.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

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

感谢任何帮助!

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

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

$ awk -v find="$find" -v replace="$replace" 's=index([=10=],find){[=10=]=substr([=10=],1,s-1) replace substr([=10=],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" '[=11=]==find{[=11=]=replace}1' file
foo
.TAG name
result input1 random_input / name1
random_input<10> input1 another_input / name2
.NTAG
bar

重组变量以读取

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

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 版本(使用 GNU sed 的 --posix),如果不是 posix,请根据您的特殊字符调整 [^0-9(){}],该字符使用转义字符表示特殊含义,例如 \+\n\d\