搜索并用多行 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\
我知道有很多类似的问题,但我猜是因为 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\