Bash 中的十六进制音译字符

Transliterate Characters in Hex in Bash

我有一组十六进制,我想将其音译为另一组十六进制,例如:

x00 -> x20
xB0 -> x20
x21 -> x40
x80-xFF -> x20
x22 -> x43

我知道我可以像这样链接 sed 语句:

sed -i.bak $'s/[\x80-\xFF]/\x20/g'

或喜欢:

sed -e 's/\x00/\x20/g;s/\xB0/\x20/g'

但是有没有办法 "break" 这些单独的更改逐行进行,以使其更具可读性?喜欢:

sed -e '
 s/\x00/\x20/g;
 s/\xB0/\x20/g;
 .
 .
 .
 ' File_In > File_out

如果不可能,可以用 perl 完成吗?谢谢。

您可以将多个表达式 (-e) 传递给 sed:

sed \
    -e 's/\x00/\x20/g' \
    -e 's/\xB0/\x20/g' \
    -e 's/\x21/\x40/g' \
    -e 's/[\x80-\xFF]/\x20/g' \
    -e 's/\x22/\x43/g' File_In > File_out

你也可以使用y命令来transliterate:

$ sed 'y/\x20\x2B/\x21\x2D/' <<< "foo bar+more"
foo!bar-more

在 Perl 中看起来像

perl -i.bak -pe '
    tr/\x00\x80-\xFF\xB0/\x20/;
    tr/\x21/\x40/;
    tr/\x22/\x43/;
' myfile

下面仍然将映射定义为映射,但是生成一个单一的、高效的tr///来完成实际工作。

perl -i~ -p <(
   perl -e'
      my %tr = (
         ( map { chr($_) => " " } 0x00, 0x80..0xFF ),
         q{!} => q{@},
         q{"} => q{C},
      );

      my $s = join "", map { sprintf "\x%02X", ord($_) } keys   %tr;
      my $r = join "", map { sprintf "\x%02X", ord($_) } values %tr;
      print("tr/$s/$r/");
  '
) myfile

更快?

sed -i~ <(
   perl -e'
      my %tr = (
         ( map { chr($_) => " " } 0x00, 0x80..0xFF ),
         q{!} => q{@},
         q{"} => q{C},
      );

      my $s = join "", map { sprintf "\x%02X", ord($_) } keys   %tr;
      my $r = join "", map { sprintf "\x%02X", ord($_) } values %tr;
      print("y/$s/$r/");
  '
) myfile

这可能对你有用(GNU sed 和 Bash):

cat <<\! | sed -f - fileIn > fileOut
s/\x00/\x20/g
s/\xB0/\x20/g
.
.
.
!

使用 here-document 并使用 -f - 选项将其作为脚本传递给 sed。