dd supprimer la plage d'octets

Compte tenu de ce file

$ cat hello.txt hello doge world 

Je voudrais enlever une gamme d'octets pour finir avec ceci

 $ cat hello.txt heorld 

Je voudrais faire cela avec dd si possible. La raison en est parce que j'utilise déjà dd pour écraser des octets de cette manière

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

Je préfère écrire dans le même file, mais un file de sortie différent serait correct.

Il s'agit de spécifier la taille de bloc, le nombre et le saut:

 $ 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 

Ce qui précède utilise trois invocations de dd . Le premier obtient les deux premiers caractères he . La seconde saute à la fin de hello et copy l'espace qui suit. Le troisième saute dans le world du dernier mot copiant tout sauf son premier caractère.

Cela a été fait avec GNU dd mais BSD dd semble qu'il devrait fonctionner aussi.

Je suppose que cela est possible en utilisant dd mais c'est un peu comme l'utilisation d'un réservoir pour tuer une mouche. Pourquoi pas

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

L'option -c signifie (pour la 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 

et pour la tail :

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

En général, pour supprimer la plage d'octets n à x inclus, vous exécuterez

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

Par exemple, pour supprimer les 4ème à 12ème octets:

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

Mark a raison

Perl pack et unpack fonction est bon de traiter avec string de largeur fixe. Si vous voulez utiliser Perl , essayez ceci:

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

Explication

  • Nous allons split la string en trois parties, $head est le début de la string jusqu'au premier octet que nous voulons supprimer, $skip est la plage d'octets que nous voulons supprimer, $tail est le rest de la string.

  • unpack model "A2 A5 A*" splita la string en trois parties comme expliqué ci-dessus.

  • Avec $skip , nous obtiendrons des espaces, l'économiserons dans $space .

  • Imprimez la concaténation de trois parties pour get la sortie désirée.

Actualisé

Comme vous ne souhaitez pas économiser de l'espace, la solution semble être plus facile:

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

Avec une string mise à jour:

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

x10 in unpack template signifier sauter les 10 octets de la string.