2

У меня поврежден файл образа диска (около 27 ГБ), в который были вставлены все \n символов \r \r. Я хочу удалить эти \r \r раньше всех \n.

Я пробовал с awk:

awk '{ sub("\r\r$", ""); print }' mangled.raw > image.raw

Но файл кажется слишком большим: «awk: ошибка времени выполнения: нехватка памяти»

Я также попробовал с sed:

sed 's/\r\r$//g' mangled.raw > image.raw

Но здесь выходной файл кажется неполным: его размер составляет всего 20 ГБ, а конец mangled.raw содержит много нулевых символов, а конец image.raw содержит содержимое файла. Каким-то образом sed, кажется, останавливается до конца.

Есть идеи, как это сделать правильно?

1 ответ1

3

Комментарий старейшины может быть правильным - это зависит от того, как произошла коррупция. Если он сделал эквивалент s/\n/\r\r\n/ то он обратим, но если он сделал s/\r*\n/\r\r\n/ то это не так.

В любом случае я бы использовал Perl для чего-то вроде этого. В отличие от sed, он с самого начала был разработан для работы со строками, которые очень длинные и могут содержать NUL и другие нетекстовые символы.

perl -pe 's/\r\r\n/\n/g' mangled.raw > image.raw

Это может занять много памяти, так как он все еще читает файл как последовательность строк, и могут быть большие сегменты файла без \n которые будут рассматриваться как одна "строка". Но если вы читаете его по блокам, вы должны быть осторожны, чтобы не пропустить последовательность \r\r\n , которая пересекает границу блока. Как это:

perl -e '
  $/=\65536;
  while(<>) {
    if(/\r\z/) {
      if(length($nextblock=<>)) {
        $_.=$nextblock;
        redo;
      }
    }
    s/\r\r\n/\n/g;
    print;
   }
' mangled.raw > image.raw

Редактировать: я понял, что приведенный выше код застрянет в бесконечном цикле, если последний байт ввода был \r . Он был обновлен для правильной обработки этого случая.

Изменить 2: однострочник Perl содержал неправильный символ замены. Это было обновлено.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .