dd remove intervalo de bytes

dd remove intervalo de bytes

Dado este arquivo

$ cat hello.txt
hello doge world

Eu gostaria de remover um intervalo de bytes para acabar com isso

$ cat hello.txt
heorld

Eu gostaria de fazer isso ddse possível. A razão é porque eu já estou usando ddpara sobrescrever bytes desta maneira

printf '\x5E' | dd conv=notrunc of=hello.txt bs=1 seek=$((0xE))

Prefiro escrever de volta no mesmo arquivo, mas um arquivo de saída diferente seria adequado.

Responder1

É uma questão de especificar o tamanho do bloco, contar e pular:

$ cat hello.txt
hello doge world
$ { dd bs=1 count=2 ; dd skip=3 bs=1 count=1 ; dd skip=6 bs=1 ; } <hello.txt 2>/dev/null
he orld

O texto acima usa três invocações de dd. O primeiro recebe os dois primeiros caracteres he. O segundo pula para o final helloe copia o espaço a seguir. O terceiro pula para a última palavra, worldcopiando tudo, exceto o primeiro caractere.

Isso foi feito comGNUddmasBSDddparece que deveria funcionar também.

Responder2

# copy the end piece into correct position
dd bs=1 seek=2 skip=12 conv=notrunc if=hello.txt of=hello.txt

# truncate
dd bs=1 seek=6 if=/dev/null of=hello.txt

Marcos está certo

Responder3

Acho que isso é possível, ddmas é como usar um tanque para matar uma mosca. Por que não

$ printf "%s %s\n" $(head -c 2 hello.txt) $(tail -c 5 hello.txt )
he orld

A -copção significa (para head):

   -c, --bytes=[-]K
          print the first K bytes of each  file;  with  the  leading  '-',
          print all but the last K bytes of each file

e para tail:

   -c, --bytes=K
          output the last K bytes; alternatively,  use  -c  +K  to  output
          bytes starting with the Kth of each file

Em geral, para remover o intervalo de bytesnparaxinclusive, você correria

( head -c n-1; head -c -x-1)  )

Por exemplo, para remover do 4º ao 12º bytes:

$ (head -c 3 hello.txt; tail -c +11 hello.txt )
hel world

Responder4

Perl packe unpackfunção são bons para lidar com strings de largura fixa. Se você quiser usar Perl, tente isto:

$ perl -le '
    ($head,$skip,$tail) = unpack("A2 A5 A*", "hello world");
    ($space) = $skip =~ m/(\s+)/;
    print $head.$space.$tail;
'
he orld

Explicação

  • Vamos dividir a string em três partes, $headé o início da string até o primeiro byte que queremos remover, $skipé o intervalo de bytes que queremos remover, $tailé o resto da string.

  • unpackO modelo "A2 A5 A*"dividirá a string em três partes, conforme explicado acima.

  • Com $skip, obteremos quaisquer espaços nele, salve-os em $space.

  • Imprima a concatenação de três partes para obter o resultado desejado.

Atualizada

Como você não quer economizar espaço, a solução parece ser mais fácil:

$ perl -le 'print unpack("A2 x5 A*","hello world")'
heorld

Com string atualizada:

$ perl -le 'print unpack("A2 x10 A*","hello doge world")'
heorld

x10no unpackmodelo, o que significa pular os 10 bytes na string.

informação relacionada