我想要做的是:查找和替换文件多行文件内容
find some_files -name '*.html' -exec sed -i "s/`cat old`/`cat new`/g" {} \;
与老和新包含换行符和斜线和其他特殊字符,这导致无法正确解析的sed 。
我读过关于如何逃生换行符与SED,并命令TR,命令的printf“%Q”,但我不能让这些正常工作,也许是因为我不完全了解他们的功能。另外,我不知道为了sed工作,我仍然需要逃脱哪些特殊字符。
我想要做的是:查找和替换文件多行文件内容
find some_files -name '*.html' -exec sed -i "s/`cat old`/`cat new`/g" {} \;
与老和新包含换行符和斜线和其他特殊字符,这导致无法正确解析的sed 。
我读过关于如何逃生换行符与SED,并命令TR,命令的printf“%Q”,但我不能让这些正常工作,也许是因为我不完全了解他们的功能。另外,我不知道为了sed工作,我仍然需要逃脱哪些特殊字符。
我不确定你想要做什么,但如果旧文件包含换行符,你可能会遇到麻烦。这是因为sed通过在每一行上应用命令来工作,所以尝试将一行与表示多行的模式匹配将不起作用,除非您明确加载更多行。
我的建议是在应用substitute命令之前将整个文件加载到sed的“缓冲区”中。然后,您必须确保新旧版本能够正确转义。此外,更令人困惑的是,旧文件(模式)的转义必须与新文件(替换)不同。
让我们先将新文件转义为“new.tmp”文件。为了清楚起见,我们将创建一个名为sed脚本 “escape_new.sed”:
#!/bin/sed -f
# Commas used as separators
s,\\,\\\\,g
s,$,\\,g
s,[/&],\\&,g
$ a/
然后运行它:sed -f escape_new.sed new > new.tmp
有三个命令我们使用逃脱:
现在让我们逃避旧文件。如上所述,我们将创建一个“escape_old.sed”脚本。在我们做之前,我们需要将整个文件加载到模式空间(sed的内部缓冲区),以便我们可以替换换行符。我们可以用下面的命令做到这一点:
: a
$! {
N
b a
}
第一个命令创建一个名为“a”的标签。第二个命令(“{”)实际上启动了一组命令。这里的魔力就是“$!”地址前缀。只有当最后一个输入行不是输入的最后一行(“$”表示输入的最后一行,“!”表示不是)时,该前缀才会指示它运行命令。组中的第一个命令将输入中的下一行附加到模式空间中。如果在最后一行执行这个“N”命令,它会终止脚本,所以我们必须小心,不要在最后一行执行它。组中的第二个命令是分支命令“b”,它将“跳转”回“a”标签。魔术是“$!”地址前缀我们有在命令之前。闭幕支架关闭该组。该组以其各自的地址前缀允许我们遍历所有行,将它们连接在一起,并在最后一行之后停止,从而允许执行任何进一步的命令。然后我们有最后的脚本:
#!/bin/sed -f
: a
$! {
N
b a
}
s,\\,\\\\,g
s,\n,\\n,g
s,[][/^$.],\\&,g
如上所述,我们需要转义特殊字符。在这种情况下,一个实际的换行符现在作为一个反斜杠后跟字母n转义。在最后一个命令中,有更多的字符需要以反斜杠作为前缀。请注意,要匹配一个方括号,它需要是方括号内的第一个字符,以防止sed将它解释为我们要匹配的字符列表的最后字符。因此,在方括号中按顺序列出的字符是][/^$.
。
再次,我们与执行:sed -f escape_new.sed old > old.tmp
现在我们可以使用这些转义在SED命令文件,但我们必须再次全部行加载到模式空间。使用与以前相同的命令,但将它们放到一行中,我们使用紧凑形式::a;$!{N;ba}
:我们现在可以在最终表达式中使用它(不包含现在位于new.tmp文件中的结束斜杠字符):
find some_files -name '*.html' -exec sed -e ":a;\$!{N;ba};s/`cat old.tmp`/`cat new.tmp`g" -i {} \;
,希望这将工作=)
请注意,我们躲过了$
符号用反斜杠,否则shell会认为我们正在试图访问最后执行的异步命令的$!
变量(结果)。
你想达到什么目的?就目前而言,对于每个html文件,如果它发现旧文件的全部内容,则将其替换为新文件的全部内容。 –
你能给我们一个例子,你想要编辑什么 – ghaschel
Daniel Landau是的,这正是我想要做的。问题是这些文件包含由sed解释的特殊字符(如斜杠),我想将它们转义出来。 – Neptilo