Это входит в уничтожать-кольцо, точно так же, как в Emacs. От Readline docuementation GNU:
При использовании команды уничтожения текст сохранен в уничтожать-кольце. Любое количество последовательных уничтожений сохранило весь уничтоженный текст вместе, так, чтобы, когда Вы дергаете его назад, Вы получили все это. Кольцо уничтожения не является конкретной строкой; текст, который Вы уничтожили на ранее введенной строке, доступен, чтобы дергаться назад позже при вводе другой строки.
Источник: http://www.gnu.org/software/bash/manual/html_node/Readline-Killing-Commands.html
Кольцо уничтожения хранится в памяти, выделенной через malloc
к символьному указателю. От kill.c
из readline источника:
/* Where to store killed text. */
static char **rl_kill_ring = (char **)NULL;
Поскольку файл может содержать нули, текстовые фильтры типа sed
не будут работать. Но можно использовать язык программирования, который может работать с нулями, например perl
или python
. Вот решение для Python 3. Это на несколько строк длиннее, чем строго необходимо, для удобочитаемости.
#!/usr/bin/python
"""Toggle the bit at the specified offset.
Syntax: <cmdname> filename bit-offset"""
import sys
fname = sys.argv[1]
# Convert bit offset to bytes + leftover bits
bitpos = int(sys.argv[2])
nbytes, nbits = divmod(bitpos, 8)
# Open in read+write, binary mode; read 1 byte
fp = open(fname, "r+b")
fp.seek(nbytes, 0)
c = fp.read(1)
# Toggle bit at byte position `nbits`
toggled = bytes( [ ord(c)^(1<<nbits) ] )
# print(toggled) # diagnostic output
# Back up one byte, write out the modified byte
fp.seek(-1, 1) # or absolute: fp.seek(nbytes, 0)
fp.write(toggled)
fp.close()
Сохраните его в файле (например, bitflip
), сделайте его исполняемым, и запустите его с именем файла для модификации и смещением в битах. Обратите внимание, что он изменяет файл на месте. Запустите его дважды с одинаковым смещением, и файл будет восстановлен.
Наконец-то я нашел решение с XXD
и DD
.
a=$(xxd -b -l 1 -seek 3 -p a.bin);b=1;echo -e "\x$((${a}^${b}))" | dd of=a.bin bs=1 seek=3 count=1 conv=notrunc
hexdump a.bin v
0000000 61 39 73 36 36 64 66 38 61 39 73 64 35 36 66 35
0000010 37 61 73 64 37 66 74 75 61 67 73 0a 61 73 64 66
hexdump b.bin v
0000000 61 39 73 37 36 64 66 38 61 39 73 64 35 36 66 35
0000010 37 61 73 64 37 66 74 75 61 67 73 0a 61 73 64 66
Но это уродливо.
Если вы действительно хотите использовать dd
, вот мерзость, которая сделает трюк, перевернув самый старший бит в данном байте. Отрегулируйте настройки команды tr
для изменения выбранного бита.
# Preparation
finger > original.txt
BYTE=3
# Here we go...
dd if=original.txt bs=1c 2>/dev/null | ( dd bs=1c count=$((BYTE-1)) ; dd bs=1c count=1 | tr '\000-\377' '\200-\377\000-\177' ; dd bs=1c ) 2>/dev/null > flipped.txt
# Demonstrate the difference (byte 3: 67 → e7)
hexdump -C original.txt | head -1
00000000 4c 6f 67 69 6e 20 20 20 20 20 4e 61 6d 65 20 20 |Login Name |
hexdump -C flipped.txt | head -1
00000000 4c 6f e7 69 6e 20 20 20 20 20 4e 61 6d 65 20 20 |Lo.in Name |
Не думаю, что есть хоть одна команда.
Вот простой скрипт, сохраните его как "flipbit
":
#!/usr/bin/perl
# Arguments: byte (starting from 0), bit (0-7), filename (otherwise stdin)
$byte = shift(@ARGV);
$bit = shift(@ARGV);
undef $/;
$file=<>;
substr($file,$byte,1) = substr($file,$byte,1) ^ chr(1<<$bit);
print $file;
test:
$ echo abb | ~/bin/flip-bit.pl 2 0 | od -xa
0000000 6261 0a63
a b c nl
это перевернуло младший бит (0) третьего символа, изменив 'b' на 'c'.
Как команда из одной строки:
perl -e '$byte=shift(@ARGV);$bit=shift(@ARGV);undef $/; $file=<>; substr($file,$byte,1) = substr($file,$byte,1) ^ chr(1<<$bit); print $file'
Простое решение с использованием головы
, хвоста
, xxd
. Пример ниже переворачивает младший бит в последнем байте file.bin .
head -c -1 file.bin > flipped.bin
LAST=`tail -c 1 file.bin | xxd -ps`
printf "%02X" $(( $((16#$LAST)) ^ 1 )) | xxd -r -ps >> flipped.bin
Вот два perl
один -вкладыша. Первый меняет файл bar
на -место:
perl -p -0777 -i -e 'substr($_,2,1)^=chr(1<<5)' bar
Второй читает файл foo
и записываетbar
perl -p -0777 -e 'substr($_,2,1)^=chr(1<<5)' < foo > bar
Чтобы адаптироваться к вашему приложению :2 выбирает, какой байт :0..file _длина -1, т. е. 2 является третьим байтом. 5 выбирает, какой бит перевернуть :0 -7, т. е. 5 — это 6-й бит. Это будет работать только для файлов, которые помещаются в память.
-p
итерация по файлу, печать после каждой итерации -0777
читать весь файл в память на каждой итерации (, поэтому будет только одна итерация)-e
запустите следующий perl-код внутри цикла substr
выберите один символ в файле, начиная с индекса 2 ^=chr
XOR этого символа с 1 сдвинутым 5 раз, т.е. 2^5
Этот ответ является упрощенной версией ответа Тоддкауфмана
.