如何用sed替换包含特殊字符(&)的字符串或url?

时间:2016-01-02 14:23:40

标签: regex linux bash sed

似乎是角色&在url中为我创造了问题。 我有一个名为 newurl.txt 的文件,其中每15分钟更新一个新网址,文件中的网址就是这样的

url/edu/playlist.m3u8?st=newcode1&e=newcode2

我有另一个名为 replaceoldurl.txt 的文件,其中旧网址需要从 newurl.txt

文件中替换

我的命令是:

cat /root/newurl.txt | xargs -I '{}' sed -r -- 's!url[^"[:space:]]+!{}!g' /root/replaceoldurl.txt

此命令可以正常工作,但它会将旧网址留在新网址旁边。 更换后看起来像这样。

url/edu/playlist.m3u8?st=oldcode1url/edu/playlist.m3u8?st=oldcode1&e=oldcode2e=newcode2

对我而言,&字符似乎会产生问题,因为它会留下旧网址而不是字符&。虽然我试图逃避角色&,但仍然无法奏效。不知道,如何让它发挥作用。在这里搜索了很多问题,但没有一个答案专门提到我的问题。

3 个答案:

答案 0 :(得分:2)

  

对我来说&人物似乎成了问题,因为它离开了   旧网址而不是字符&amp ;.虽然我试图逃避这个角色   &,但仍然无效。不知道,如何让它发挥作用。搜索了很多   这里有问题,但没有一个答案专门提到我的   问题。

这是正确的,'&'是一个特殊的角色。这里有一个参考资料来自sed的手册,它解释了'&'的行为。

  

S /的regexp /更换/

     

尝试将regexp与模式空间匹配。如果成功,请替换与替换匹配的部分。替换可能包含特殊字符&引用模式空间中匹配的那部分,特殊转义\ 1到\ 9引用正则表达式中相应的匹配子表达式。

你是如何逃脱'&'的?

您可以尝试修改cat / sed命令:

cat newurl.txt | sed 's/\&/\\\\&/g' | xargs  -I {} sed -r -- 's!url[^"[:space:]]+!{}!g' oldurl.txt

您可以在此解释为什么需要执行\\\\&

$ cat newurl.txt 
url/edu/playlist.m3u8?st=newcode1&e=newcode2

$ cat newurl.txt | sed 's/\&/\\&/g' 
url/edu/playlist.m3u8?st=newcode1\&e=newcode2

$ cat newurl.txt | sed 's/\&/\\&/g' | xargs  -I {} echo {}
url/edu/playlist.m3u8?st=newcode1&e=newcode2

$ cat newurl.txt | sed 's/\&/\\\\&/g' | xargs  -I {} echo {}
url/edu/playlist.m3u8?st=newcode1\&e=newcode2

如果你想进行内联更改,只需将'-i'选项传递给sed,如下所示:

$ cat newurl.txt | sed 's/\&/\\\\&/g' | xargs  -I {} sed -r -i -- 's!url[^"[:space:]]+!{}!g' oldurl.txt    

答案 1 :(得分:1)

&是一个特殊字符。在s///命令中,右侧的&被左侧匹配的整个表达式替换。所以你需要逃避它:\&

可能的解决方案是:

cat /root/newurl.txt | \
sed 's/\&/\\\\&/g'  |  \
xargs -I '{}' sed -r -- 's!url.+!{}!g' /root/replaceoldurl.txt

您需要使用\\\\&获取\&输出的xargs。如果您想使用-i选项,则不应将-r替换为:

cat /root/newurl.txt | \
sed 's/\&/\\\\&/g'  |  \
xargs -I '{}' sed -ri -- 's!url.+!{}!g' /root/replaceoldurl.txt

答案 2 :(得分:0)

您已经获得了使用xargs的解决方案,例如

cat newurl.txt | sed 's/\&/\\\\&/g' | xargs  -I {} sed -r -- 's!url[^"[:space:]]+!{}!g' oldurl.txt

我从您的评论中看到您要使用-i(原位)选项。您不必将-r替换为-i;你可以像

一样使用它们
...| xargs  -I {} sed -ri -- 's!url[^"[:space:]]+!{}!g' oldurl.txt

或者,您可以丢失-r选项并转义+量词

... | xargs  -I {} sed -i -- 's!url[^"[:space:]]\+!{}!g' oldurl.txt

如果两个文件都包含一个一个 URL ,则此解决方案将有效。

但它必须是一个唯一的解决方案吗?如果没有,我可能会用一个简单的Bash脚本来解决这个问题:

#!/bin/bash
while read URL;do
    sed -i "\!${URL%?st=*}! {s!.*!${URL//&/\\&}!}" oldurl.txt
done < newurl.txt

这也将处理具有多个URL的文件,例如:克,

$ cat oldurl.txt
Some random
url/edu/playlist3.m3u8?st=oldcode31&e=oldcode32
lines
url/edu/playlist2.m3u8?st=oldcode21&e=oldcode22

url/edu/playlist1.m3u8?st=oldcode11&e=oldcode12
of code
$ cat newurl.txt
url/edu/playlist1.m3u8?st=newcode11&e=newcode12
url/edu/playlist2.m3u8?st=newcode21&e=newcode22
url/edu/playlist3.m3u8?st=newcode31&e=newcode32

生成的oldurl.txt文件:

$ cat oldurl.txt
Some random
url/edu/playlist3.m3u8?st=newcode31&e=newcode32
lines
url/edu/playlist2.m3u8?st=newcode21&e=newcode22

url/edu/playlist1.m3u8?st=newcode11&e=newcode12
of code