如何搜索 &替换 sed 和 awk(和 perl)中的任意文字字符串 [英] How to search & replace arbitrary literal strings in sed and awk (and perl)
问题描述
假设我们在文件中有一些任意文字,我们需要用其他文字替换它们.
Say we have some arbitrary literals in a file that we need to replace with some other literal.
通常,我们只需使用 sed(1) 或 awk(1) 并编写如下代码:
Normally, we'd just reach for sed(1) or awk(1) and code something like:
sed "s/$target/$replacement/g" file.txt
但是,如果 $target 和/或 $replacement 可能包含对 sed(1) 敏感的字符,例如正则表达式,该怎么办?你可以逃避它们,但假设你不知道它们是什么——它们是任意的,好吗?您需要编写一些代码来转义所有可能的敏感字符 - 包括/"分隔符.例如
But what if the $target and/or $replacement could contain characters that are sensitive to sed(1) such as regular expressions. You could escape them but suppose you don't know what they are - they are arbitrary, ok? You'd need to code up something to escape all possible sensitive characters - including the '/' separator. eg
t=$( echo "$target" | sed 's/./\./g; s/*/\*/g; s/[/\[/g; ...' ) # arghhh!
对于这么简单的问题,这很尴尬.
That's pretty awkward for such a simple problem.
perl(1) 有 Q ... E 引号但即使这样也无法处理 $target
中的 '/' 分隔符.
perl(1) has Q ... E quotes but even that can't cope with the '/' separator in $target
.
perl -pe "s/Q$targetE/$replacement/g" file.txt
我刚刚发布了一个答案!!所以我真正的问题是,有没有更好的方法在 sed/awk/perl 中进行文字替换?"
I just posted an answer!! So my real question is, "is there a better way to do literal replacements in sed/awk/perl?"
如果没有,我会把它留在这里,以防它有用.
If not, I'll leave this here in case it comes in useful.
推荐答案
我又来了!
这是使用 xxd(1) 的一种更简单的方法:
Here's a simpler way using xxd(1):
t=$( echo -n "$target" | xxd -p | tr -d '
')
r=$( echo -n "$replacement" | xxd -p | tr -d '
')
xxd -p file.txt | sed "s/$t/$r/g" | xxd -p -r
...所以我们使用 xxd(1) 对原始文本进行十六进制编码,并使用十六进制编码的搜索字符串进行搜索替换.最后我们对结果进行十六进制解码.
... so we're hex-encoding the original text with xxd(1) and doing search-replacement using hex-encoded search strings. Finally we hex-decode the result.
我忘记从 xxd 输出 (| tr -d '
'
) 中删除
以便模式可以跨越 60 列输出xxd.当然,这依赖于 GNU sed
对非常长的行进行操作的能力(仅受内存限制).
I forgot to remove
from the xxd output (| tr -d '
'
) so that patterns can span the 60-column output of xxd. Of course, this relies on GNU sed
's ability to operate on very long lines (limited only by memory).
这也适用于多行目标,例如
this also works on multi-line targets eg
target=$'foo bar'替换=$'bar foo'
target=$'foo bar' replacement=$'bar foo'
这篇关于如何搜索 &替换 sed 和 awk(和 perl)中的任意文字字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!