dd remove intervalo de bytes

4

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 com dd , se possível. A razão é porque eu sou já está usando dd para sobrescrever bytes dessa maneira

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

Eu prefiro escrever no mesmo arquivo, mas um arquivo de saída diferente seria ok.

    
por Steven Penny 11.05.2014 / 04:44

4 respostas

5

É 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 acima usa três invocações de dd . O primeiro recebe os dois primeiros caracteres he . O segundo pula para o final de hello e copia o espaço que se segue. O terceiro pula para a última palavra world copiando tudo exceto seu primeiro caractere.

Isso foi feito com GNU dd , mas BSD dd parece que deve funcionar também.

    
por 11.05.2014 / 06:58
3

Eu acho que isso é possível usando dd , mas é 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 opção -c 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 bytes n para x , você executaria

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

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

$ (head -c 3 hello.txt; tail -c +11 hello.txt )
hel world
    
por 11.05.2014 / 04:54
3
# 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

    
por 11.05.2014 / 15:40
0

Perl pack e unpack function é goot ao lidar com uma string 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 restante string.

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

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

  • Imprima a concatenação de três partes para obter a saída desejada.

Atualizado

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

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

com uma string atualizada:

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

x10 in unpack template significado ignore os 10 bytes em string.

    
por 11.05.2014 / 18:06