Есть ли вызов sed
редактирования «на месте» без резервного копирования, который работает как в Linux, так и в Mac? В то время как BSD, sed
поставляемый с OS X, кажется, нуждается sed -i '' …
, sed
дистрибутивы GNU Linux обычно поставляются с интерпретацией кавычек как пустое имя входного файла (вместо расширения резервной копии), и sed -i …
вместо этого нуждается .
Существует ли какой-либо синтаксис командной строки, который работает с обоими вариантами, чтобы я мог использовать один и тот же сценарий в обеих системах?
Ответы:
Если вы действительно хотите просто использовать
sed -i
«простой» способ, следующие команды работают как на GNU, так и на BSD / Macsed
:Обратите внимание на отсутствие места и точки.
Доказательство:
Очевидно, что вы можете просто удалить
.bak
файлы.источник
sed
)sed
не принимает позиционноеcommand
аргумент при вызове с-i
- он должен быть снабжен другим флагом,-e
. Таким образом, команда становится:sed -i.bak -e 's/foo/bar/' filename
sed -i.bak 's/foo/bar/' file && rm file.bak
Это работает с GNU sed, но не на OS X:
Это работает на OS X, но не с GNU sed:
На OS X вы
sed -i -e
так как расширение файла резервной копии будет установлено на-e
sed -i'' -e
по тем же причинам - ему нужно пространство между-i
и''
.источник
-i
и-i''
идентичны во время разбора оболочки;sed
не может вести себя по-разному на тех двух первых вызовах, потому что он получает точно такие же аргументы.На OSX я всегда устанавливаю версию GNU sed через Homebrew, чтобы избежать проблем в сценариях, потому что большинство сценариев были написаны для версий GNU sed.
Тогда ваш BSD sed будет заменен на GNU sed.
Кроме того, вы можете установить без имен по умолчанию, но затем:
PATH
как указано после установкиgnu-sed
gsed
или вsed
зависимости от вашей системыисточник
--with-default-names
было удалено из доморощенного-ядра , больше информации в этом ответе. при установкеgnu-sed
сейчас в инструкции по установке указано, что вам нужно добавитьgnubin
в свойPATH
:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Как спрашивает Нуфал Ибрагим , почему вы не можете использовать Perl? Любой Mac будет иметь Perl, и очень мало дистрибутивов Linux или BSD, которые не включают какую-либо версию Perl в базовую систему. Одной из единственных сред, в которых может отсутствовать Perl, может быть BusyBox (который работает как GNU / Linux, за
-i
исключением того, что не может быть указано расширение для резервного копирования).Как рекомендует Исмаил ,
и это кажется лучшим решением почти в любом случае, чем сценарии, псевдонимы или другие обходные пути, чтобы справиться с фундаментальной несовместимостью
sed -i
между GNU / Linux и BSD / Mac.источник
perl
является частью стандартной спецификации Linux с 1 мая 2009 г. refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/…Нет способа заставить его работать.
Одним из способов является использование временного файла, такого как:
Это работает на обоих
источник
Ответ: Нет.
Первоначально принятый ответ на самом деле не делает то, что запрашивается (как отмечено в комментариях). (Я нашел этот ответ, когда искал причину
file-e
появления «случайно» в моих каталогах.)По-видимому, нет способа заставить
sed -i
работать последовательно как MacOS, так и Linuces.Моя рекомендация, для чего бы это ни стоило, не обновлять на месте
sed
(который имеет сложные режимы сбоев), а генерировать новые файлы и переименовывать их впоследствии. Другими словами: избегайте-i
.источник
-i
Вариант не является частью POSIX Sed . Более переносимый метод - использовать Vim в режиме Ex:%
выбрать все строкиs
замещатьx
сохранить и закрытьисточник
Вот еще одна версия, которая работает на Linux и MacOS, не используя
eval
и не удаляя файлы резервных копий. Он использует массивы Bash для храненияsed
параметров, что чище, чем использованиеeval
:Это не создает файл резервной копии, ни файл с добавленными кавычками.
источник
sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '')
sed "${sedi[@]}" -e 's/foo/bar/' target.file
Ответ Стива Пауэлла совершенно верный: на странице MAN для sed в OSX и Linux (Ubuntu 12.04) подчеркивается несовместимость использования sed на месте для двух операционных систем.
JFYI, не должно быть пробела между -i и любыми кавычками (которые обозначают пустое расширение файла), используя версию sed для Linux, таким образом
Sed Linux Man Page
и
Страница man sed OSX
Я обошел это в скрипте, используя команду alias'd и вывод имени операционной системы « uname » в bash «if». Попытка сохранить зависящие от ОС строки команд в переменных была неудачной при интерпретации кавычек. Использование ' shopt -s expand_aliases ' необходимо для расширения / использования псевдонимов, определенных в вашем скрипте. Использование Shopt рассматривается здесь .
источник
Если вам нужно сделать
sed
на месте вbash
сценарии, и вы не хотите, чтобы на месте в результате с файлами .bkp, и у вас есть способ обнаружить ОС (скажем, с помощью ostype.sh ), - тогда следующий хак сbash
встроенной оболочкойeval
должен работать:источник
Вы можете использовать губку. Sponge - это старая Unix-программа, находящаяся в пакете moreutils (как в Ubuntu и, вероятно, в Debian, так и в Homebrew в Mac).
Он будет буферизовать весь контент из канала, дождаться закрытия канала (возможно, это означает, что входной файл уже закрыт), а затем перезаписать:
Со страницы руководства :
источник
Следующее работает для меня на Linux и OS X:
sed -i' ' <expr> <file>
например, для файла,
f
содержащегоaaabbaaba
sed -i' ' 's/b/c/g' f
дает
aaaccaaca
как на Linux и Mac. Обратите внимание, что есть строка в кавычках, содержащая пробел , без пробела между-i
строкой и. Работают одинарные или двойные кавычки.В Linux я использую
bash
версию 4.3.11 под Ubuntu 14.04.4 и на Mac версии 3.2.57 под OS X 10.11.4 El Capitan (Darwin 15.4.0).источник
Я столкнулся с этой проблемой. Единственным быстрым решением было заменить sed в mac на версию gnu:
источник