我正在尝试在任意长度的十六进制字符字符串中自动交换字符 1 和 2、3 和 4 等。
例子:
A627E39B
变成:
6A723EB9
看起来这应该可以使用 sed 或其他 *nix 文本实用程序之一来实现,但到目前为止我还没有找到任何示例。
答案1
您可以使用反向引用:
echo A627E39B | sed 's/\(.\)\(.\)/\2\1/g'
这会找到所有出现的两个字符并交换它们。
作为格伦·杰克曼指出,启用扩展正则表达式(-E
w/ GNU、BSD 或toybox
sed
s) 避免必须转义括号:
echo A627E39B | sed -E 's/(.)(.)/\2\1/g'
答案2
有一个工具本身专门支持该功能:
dd
使用swab
(西南瓦p乙ytes)转换:
% echo ABCD | dd conv=swab
BADC
0+1 records in
0+1 records out
5 bytes (5 B) copied, 0.000109277 s, 45.8 kB/s
您需要添加2> /dev/null
以丢弃日志输出:
% echo ABCD | dd conv=swab 2> /dev/null
BADC
警告:如果您发送偶数个(可打印)字符,这将几乎满足您的要求。但是,如果你给它奇数个可打印字符——假设 2 个n+1 — 然后dd
将末尾的换行符作为 (2n+2)个字符,并将其与第 (2) 个字符交换n+1)个。所以,
% echo ABCDE | dd conv=swab 2> /dev/null
发送
A B C D E \n
到dd
,这给了你
B A D C \n E
后退;这看起来像
BADC
E
您可以通过指定在末尾抑制换行符的-n
选项(或者仅使用而不添加换行符)来解决此问题。如果您要将输出显示到屏幕上,那么为了完整起见,您应该在最后添加换行符:echo
printf
% echo -n ABCDE | dd conv=swab 2> /dev/null; echo
BADCE
% printf "%s" ABCDE | dd conv=swab 2> /dev/null; printf "\n"
BADCE
答案3
您还可以使用perl
:
$ echo A627E39B | perl -CLS -nle 'print map {~~reverse} unpack "(a2)*"'
6A723EB9