用包含特殊字符的长字符串(每次都有变化)替换文本

时间:2015-08-27 21:24:25

标签: regex sed

查找并替换文件中的文本。查找单词始终相同,并且替换字符串会一直变化

我正在尝试一个简单的sed脚本(test.sh)来实现这个,它使用一个参数(一个带有特殊字符的长字符串):

sed -i "s/#####REPLACE#####/$1/g" file.txt

结果应该使用我传递给脚本#####REPLACE#####的参数替换test.sh

参数一直在变化,并且包含许多特殊字符(如下所示):

"abc"/def:-/ghi$jklmno-pqrblah..blah..very..long..string

我正在尝试的命令是:

./test.sh "abc"/def:-/ghi$jklmno-pqrblah..blah..very..long..string

它给出了以下信息:

sed: -e expression #1, char 25: unknown option to `s'

我有很多文件(例如file1.txtfile2.txtfile3.txt),相同的公共文本#####REPLACE#####将被相同的参数"abc"/def:-/ghi$jklmno-pqrblah..blah..very..long..string替换。

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

一种选择是使用awk:

awk -v replace="$1" '{ gsub(/#####REPLACE#####/, replace); print }' file

这将awk变量replace设置为等于传递给函数$1的第一个参数,然后对file的每一行执行全局替换。

要覆盖文件"就地",只需使用awk ... file > tmp && mv tmp file

这种方法优于使用sed的优点是替换字符串*中出现的字符并不重要;它们永远不会导致语法错误。

*正如评论中指出的那样,有一个角色会破坏:&

由于您只对执行字符串替换(而非正则表达式替换)感兴趣,另一种选择是使用以下内容:

awk -v replace="$1" '{
    out = ""
    while(match($0, /#####REPLACE#####/)) {
        out = out substr($0, 0, RSTART - 1) replace
        $0 = substr($0, RSTART + RLENGTH)
    }
print out $0}' file

使用输入记录out和变量$0的组合构建替换字符串replace

答案 1 :(得分:0)

问题是你在sed中使用/作为正则表达式分隔符,同样的字符也是替换字符串的一部分。在sed中使用备用正则表达式分隔符:

sed -i "s~#####REPLACE#####~$1~g" file.txt

这是假设~(代字号)不在替换文本中。如果是这种情况,那么您甚至可以使用控制字符,例如^A ctrl V A (压在一起)作为正则表达式分隔符。

sed -i "s^A#####REPLACE#####^A$1^Ag" file.txt

PS:如果您想在&中将&作为文字$1传递,请将其作为\&

转义