Como posso trocar a ordem de cada par de dois caracteres em uma string?

2

Eu estou tentando automatizar a troca de caracteres 1 e 2, 3 e 4, etc, em uma cadeia de caracteres hexadecimais de tamanho arbitrário.

Exemplo:

A627E39B

torna-se:

6A723EB9

Parece que isso deve ser possível usando o sed ou um dos outros utilitários de texto * nix, mas até agora não consegui encontrar nenhum exemplo.

    
por Eet 12.05.2015 / 00:05

3 respostas

7

Você pode usar referências anteriores:

echo A627E39B | sed 's/\(.\)\(.\)//g'

Isso localiza todas as ocorrências de dois caracteres e as troca.

Como glenn jackman apontou, permitindo expressões regulares estendidas ( -E w / GNU, BSD ou toybox sed s ) evita ter que escapar dos parênteses:

echo A627E39B | sed -E 's/(.)(.)//g'
    
por 12.05.2015 / 00:08
2

Há uma ferramenta que especificamente suporta nativamente essa função: dd com a conversão de swab ( swa p b 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

Você deve adicionar 2> /dev/null para descartar a saída do registro:

% echo ABCD | dd conv=swab 2> /dev/null
BADC

Aviso: Isso fará praticamente o que você deseja se você enviá-lo um número par de caracteres (imprimíveis). Mas se você der um número ímpar de caracteres imprimíveis - digamos 2 n +1 - então dd terá a nova linha no final como o caractere (2 n +2) th , e troque-o com o (2 n +1) th . Então,

% echo ABCDE | dd conv=swab 2> /dev/null

envia

Um B C D E \ n

para dd , o que lhe dá

B A D C \ n E

de volta; isso será parecido com

BADC
E

Você pode contornar isso especificando a opção -n para echo para suprimir a nova linha no final (ou apenas use printf sem adicionar uma nova linha). Se você está exibindo a saída para a tela, então, por completo, você deve adicionar uma nova linha no final:

% echo -n ABCDE | dd conv=swab 2> /dev/null; echo
BADCE

% printf "%s" ABCDE | dd conv=swab 2> /dev/null; printf "\n"
BADCE
    
por 12.05.2015 / 08:07
0

Você também pode usar perl :

$ echo A627E39B | perl -CLS -nle 'print map {~~reverse} unpack "(a2)*"'
6A723EB9
    
por 12.05.2015 / 04:26