8

我的问题的答案可能存在于 SO 上,但老实说,我已经努力寻找并找不到它。我得到的最接近的是这个问答,但我无法在我的机器上重现他们的结果(OSX 10.7.5,使用bash)。

这是问题的本质:我无法将(例如for )sed解释为十六进制字符。尤其让我抓狂的是:\xnn\x41A

echo -e '\x41' 

结果A- 所以操作系统及其功能理解我的十六进制代码......

echo -e '\x41' | sed 's/A/B/'

结果- 正如预期的那样,因为十六进制代码在看到它之前B被转换为Ased

echo A | sed 's/\x41/B/'

结果A- 我本来期望的B

我尝试过类似的事情

echo A | LANG='C' sed 's/\x41/B/'

结果是A

echo A | LANG='' sed 's/\x41/B/'

同上...

echo A | sed 's/[\x41]/B/'

结果是A

但...

echo A | sed 's/[\x41-\x41]/B/'

结果B???

我完全愚蠢吗?还是真的有什么奇怪的地方sed?它显然可以解释一个范围内的十六进制代码,但我不能让它被解释为单个字符。我错过了什么?

请注意 - 我正在寻找既能解释上述行为为何如此的答案,也能在 OSX 平台上的字符串中的任何位置插入单个十六进制代码的方法。这意味着在“搜索”和命令的“替换”部分。因为我显然已经表明我可以使用 [\xnn-\xnn]; 搜索单个字符;这不是我要找的答案。seds/

提前致谢!

4

2 回答 2

12

没有关于“操作系统及其功能理解”的一般概念——每个程序、函数等都理解自己特定的元字符集、转义符等。而且碰巧sed不使用十六进制代码。但是 bash 会(如果你要求的话),所以你可以在调用之前让它翻译sed它们$''

$ echo A | sed $'s/\x41/B/'
B

请注意,这也会在将其他转义序列传递给 之前对其进行解释sed,因此如果要将任何转义传递给sed,则需要对它们进行双重转义,或切换引号模式,以便只有相关部分位于$''

$ echo A | sed $'s/\\(\x41\\)/B\\1/' # double-escapes for sed's escape sequences
BA
$ echo A | sed 's/\('$'\x41''\)/B\1/' # equivalent with different quote modes
BA
$ echo A | sed 's/\(A\)/B\1/' # simplest equivalent version
BA

如果你想解释一个变量而不是常量字符串中的十六进制转义,那么你几乎必须使用 shell 的printf内置函数:

$ hex=41
$ echo A | sed "s/$(printf "\x$hex")/B/"
B
于 2013-02-15T07:20:12.033 回答
6

@GordonDavisson 给了我尝试另外两件事的灵感……

首先 - 我突然想知道我是否误解了

echo A | sed 's/[\x41-\x41]/B/'

我认为这意味着sed理解\xnn某个范围内的代码,但我错了。当我尝试

echo A | sed 's/[\x40-\x40]/B/'

尽管我认为我不再将( ) 包含在该范围内,但我仍然得到了输出。显然,是在以某种不同于我预期的方式解释我的范围。通过更仔细地查看页面解决了这个问题。它说BA\x41sedman re_format

[...] 所有其他特殊字符,包括 `\',在括号表达式中失去其特殊意义。

但后来我得到了灵感:如果echo -e可以扩展字符串,也许我可以用它来喂我想要的字符串sed......

echo "This?" | sed `echo -e 's/\x54\x68\x69\x73\x3F/\x59\x65\x73\x21/'`

生产Yes!

echo "That?" | sed `echo -e 's/\x54\x68\x69\x73\x3F/\x59\x65\x73\x21/'`

生产That?

当然,在这种情况下,\xnn字符只代表纯 ASCII 对字符串进行解码's/This?/Yes!/',但它确实建立了将十六进制字符插入到字符串中的原则sed。这无助于澄清的唯一一件事是“如果您的echo语句打印需要在sed. sed. 我仍然怀疑这是可能的......在阅读文档后更是如此sed(声称使用“旧”正则表达式,尽管 -E 标志可以使其使用“扩展”表达式,并将用户引导到re_format手册页有关详细信息;以及由以下人员re_syntax引用的页面re_format. 在这些之间,看起来确实应该直接添加一个十六进制字符串......

我将此信息添加为我的问题的“答案”而不是“编辑”,因为我相信它开始回答我的问题......期待评论!

于 2013-02-15T13:46:46.097 回答