dd удалить диапазон байтов

dd удалить диапазон байтов

Учитывая этот файл

$ 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и unpackfunction хорошо справляются со строкой фиксированной ширины. Если вы хотите использовать 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 байт в строке.

Связанный контент