Почему sed добавляет новую строку в OSX?

echo -n 'I hate cats' > cats.txt
sed -i '' 's/hate/love/' cats.txt

Это правильно изменяет слово в файле, но также добавляет новую строку в конец файла. Зачем? Это происходит только в OSX, а не в Ubuntu и т.д. Как я могу остановить его?

Ответ 1

echo -n 'I hate cats' > cats.txt

Эта команда заполняет содержимое "cats.txt" с 11 символами между одинарными кавычками. Если вы проверите размер cats.txt на этом этапе, оно должно быть 11 байтов.

sed -i '' 's/hate/love/' cats.txt

Эта команда будет считывать файл cats.txt по строке и заменять его файлом, в котором каждая строка имеет первый экземпляр "ненависти", замененный на "любовь" (если такая экземпляр существует). Важная часть - это понимание того, что такое линия. На странице sed man:

 Normally, sed cyclically copies a line of input, not including its
 terminating newline character, into a pattern space, (unless there is
 something left after a ``D'' function), applies all of the commands
 with addresses that select that pattern space, copies the pattern
 space to the standard output, appending a newline, and deletes the
 pattern space.

Обратите внимание на часть appending a newline. В вашей системе sed все еще интерпретирует ваш файл как содержащий одну строку, хотя нет завершающей новой строки. Таким образом, вывод будет состоять из 11 символов плюс добавленная новая строка. На других платформах это не обязательно будет так. Иногда sed полностью пропускает последнюю строку в файле (фактически удаляя ее), потому что это не строка! Но в вашем случае sed в основном фиксирует файл для вас (как файл без строк в нем, он разбит на ввод sed).

Подробнее см.: Почему текстовые файлы заканчиваются новой строкой?

См. этот вопрос для альтернативного подхода к вашей проблеме: SED добавляет новую строку в конец

Ответ 2

Еще одна вещь, которую вы можете сделать, это следующее:

echo -n 'I hate cats' > cats.txt
SAFE=$(cat cats.txt; echo x)
SAFE=$(printf "$SAFE" | sed -e 's/hate/love/')
SAFE=${SAFE%x}

Таким образом, если cats.txt заканчивается в новой строке, он сохраняется. Если это не так, оно не добавляется.

Ответ 3

Это сработало для меня. Мне не нужно было использовать промежуточный файл.

OUTPUT=$( echo 'I hate cats' | sed 's/hate/love/' )
echo -n "$OUTPUT"

Ответ 4

Обратите внимание, что GNU sed не добавляет новую строку в Mac OS.