如何搜寻和替换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$target\E/$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 '\n')
r=$( echo -n "$replacement" | xxd -p | tr -d '\n')
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 '\n'
)中删除\n
,以便模式可以跨越xxd的60列输出.当然,这取决于GNU sed
在很长的行(仅受内存限制)上进行操作的能力.
I forgot to remove \n
from the xxd output (| tr -d '\n'
) 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 \ nbar' 替换= $'bar \ nfoo'
target=$'foo\nbar' replacement=$'bar\nfoo'
这篇关于如何搜寻和替换sed和awk(和perl)中的任意文字字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!