Учитывая этот файл
$ cat hello.txt
hello doge world
Я хотел бы удалить диапазон байтов, чтобы получить это
$ cat hello.txt
heorld
Я хотел бы сделать это с, dd
если это возможно. Причина в том, что я уже использую dd
для перезаписи байтов таким образом
printf '\x5E' | dd conv=notrunc of=hello.txt bs=1 seek=$((0xE))
Я предпочитаю записывать данные в тот же файл, но можно было бы использовать и другой выходной файл.
решение1
Это вопрос указания размера блока, количества и пропуска:
$ 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
Вышеприведенный пример использует три вызова dd
. Первый получает первые два символа he
. Второй переходит к концу hello
и копирует следующий за ним пробел. Третий переходит к последнему слову, world
копируя все, кроме первого символа.
Это было сделано сГНУdd
ноБСДdd
похоже, это тоже должно работать.
решение2
# 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
решение3
Я думаю, это возможно с помощью, dd
но это как использовать танк, чтобы убить муху. Почему бы и нет
$ printf "%s %s\n" $(head -c 2 hello.txt) $(tail -c 5 hello.txt )
he orld
Опция -c
означает (для 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
и для tail
:
-c, --bytes=K
output the last K bytes; alternatively, use -c +K to output
bytes starting with the Kth of each file
В общем случае, чтобы удалить диапазон байтовнкИксвключительно, вы бы запустили
( head -c n-1; head -c -x-1) )
Например, чтобы удалить байты с 4-го по 12-й:
$ (head -c 3 hello.txt; tail -c +11 hello.txt )
hel world
решение4
Perl pack
и unpack
function хорошо справляются со строкой фиксированной ширины. Если вы хотите использовать Perl
, попробуйте это:
$ perl -le '
($head,$skip,$tail) = unpack("A2 A5 A*", "hello world");
($space) = $skip =~ m/(\s+)/;
print $head.$space.$tail;
'
he orld
Объяснение
Мы разделим строку на три части:
$head
— начало строки до первого байта, который мы хотим удалить,$skip
— диапазон байтов, который мы хотим удалить,$tail
— остальная часть строки.unpack
Шаблон"A2 A5 A*"
разделит строку на три части, как описано выше.С помощью
$skip
мы извлечем из него все пробелы и сохраним его в$space
.Распечатайте объединение трех частей, чтобы получить желаемый результат.
Обновлено
Поскольку вы не хотите экономить место, решение кажется более простым:
$ perl -le 'print unpack("A2 x5 A*","hello world")'
heorld
С обновленной строкой:
$ perl -le 'print unpack("A2 x10 A*","hello doge world")'
heorld
x10
в unpack
шаблоне означает пропуск 10 байт в строке.