sed in-place flaga, która działa zarówno na Mac (BSD) i Linux

Czy istnieje wywołanie sed todo in-place editing without backups, które działa zarówno na Linuksie, jak i Macu? Podczas gdy BSD sed dostarczane wraz z OS X wydaje się potrzebować sed -i '' …, dystrybucje GNU sed Linux zazwyczaj są dostarczane z interpretacją cudzysłowów jako pustej nazwy pliku wejściowego (zamiast rozszerzenia kopii zapasowej), a zamiast tego potrzebuje sed -i ….

Czy jest jakaś składnia wiersza poleceń, która działa z obydwoma smakami, więc mogę używać tego samego skryptu na obu systemach?

Author: Alex Dupuy, 2011-04-17

14 answers

Jeśli naprawdę chcesz używać sed -i w "łatwy" sposób, poniższe instrukcje działają zarówno na GNU, jak i BSD / Mac sed:

sed -i.bak 's/foo/bar/' filename

Zwróć uwagę na brak miejsca i kropki.

Dowód:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

Oczywiście można wtedy po prostu usunąć .bak pliki.

 233
Author: kine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 20:28:35

To działa z GNU sed, ale nie na OS X:

sed -i -e 's/foo/bar/' target.file
sed -i'' -e 's/foo/bar/' target.file

To działa na OS X, ale nie z GNU sed:

sed -i '' -e 's/foo/bar/' target.file

Na OS X you

  • nie można użyć sed -i -e, ponieważ rozszerzenie pliku kopii zapasowej będzie ustawione na -e
  • nie może używać sed -i'' -e z tych samych powodów-potrzebuje spacji między -i a ''.
 119
Author: dnadlinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 20:28:25

Kiedy na OSX, zawsze instaluję wersję GNU sed poprzez Homebrew, aby uniknąć problemów w skryptach, ponieważ większość skryptów została napisana dla wersji GNU sed.

brew install gnu-sed --with-default-names

Wtedy twój BSD sed zostanie zastąpiony przez GNU sed.

Alternatywnie, można zainstalować bez domyślnych nazw, ale wtedy:

  • zmień swoje PATH zgodnie z instrukcją po zainstalowaniu gnu-sed
  • sprawdź w swoich skryptach, aby wybrać pomiędzy gsed lub sed w zależności od systemu
 47
Author: Lewy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 20:27:50

Jak Noufal Ibrahim pyta, dlaczego nie możesz używać Perla? Każdy Mac będzie miał Perla i jest bardzo niewiele dystrybucji Linuksa lub BSD, które nie zawierają jakiejś wersji Perla w systemie bazowym. Jednym z niewielu środowisk, w którym może brakować Perla, jest BusyBox (który działa jak GNU / Linux dla -i, z tą różnicą, że nie można podać rozszerzenia kopii zapasowej).

As Ismail zaleca,

Ponieważ perl jest dostępny wszędzie, ja po prostu perl -pi -e s,foo,bar,g target.file

I wydaje się to lepszym rozwiązaniem prawie w każdym przypadku niż skrypty, aliasy lub inne obejścia, aby poradzić sobie z podstawową niekompatybilnością sed -i pomiędzy GNU/Linuksem a BSD/Mac.

 19
Author: Alex Dupuy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:43

Nie ma sposobu, aby to działało.

Jednym ze sposobów jest użycie pliku tymczasowego, takiego jak:

TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX`
sed -e "s/abc/def/" some/file > $TMP_FILE
mv $TMP_FILE some/file

To działa na obu

 16
Author: analogue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 20:27:44

ODPOWIEDŹ: Nie.

Pierwotnie przyjęta odpowiedź faktycznie nie robi tego ,co jest wymagane (jak zaznaczono w komentarzach). (Znalazłem tę odpowiedź szukając powodu, dla którego A file-e pojawia się" losowo " w moich katalogach.)

Najwyraźniej nie ma sposobu, aby sed -i działać konsekwentnie zarówno na MacOS, jak i Linuce.

Moim zaleceniem, o ile jest to warte, nie jest aktualizacja-in-place z sed (która ma złożone tryby awarii), ale generowanie nowych pliki i zmienić ich nazwy później. Innymi słowy: unikać -i.

 14
Author: Steve Powell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-04 09:38:45

Opcja -i nie jest częścią POSIX Sed . Bardziej przenośną metodą byłoby aby użyć Vima w trybie Ex:

ex -sc '%s/alfa/bravo/|x' file
  1. % Wybierz wszystkie linie

  2. s zastąp

  3. x Zapisz i zamknij

 11
Author: Steven Penny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-24 13:50:34

Oto kolejna wersja, która działa na Linuksie i macOS bez używania eval i bez konieczności usuwania plików kopii zapasowych. Używa tablic Bash do przechowywania parametrów sed, co jest czystsze niż użycie eval:

# Default case for Linux sed, just use "-i"
sedi=(-i)
case "$(uname)" in
  # For macOS, use two parameters
  Darwin*) sedi=(-i "")
esac

# Expand the parameters in the actual call to "sed"
sed "${sedi[@]}" -e 's/foo/bar/' target.file

To nie tworzy pliku kopii zapasowej, ani pliku z dołączonymi cudzysłowami.

 9
Author: nwinkler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 20:27:36

Odpowiedź Steve 'a Powella jest całkiem poprawna, zapoznanie się ze stroną MAN dla sed na OSX i Linuksie (Ubuntu 12.04) podkreśla kompatybilność w "in-place" sed wykorzystania w obu systemach operacyjnych.

JFYI, nie powinno być spacji między-i A cudzysłowami (które oznaczają puste rozszerzenie pliku) przy użyciu Linuksowej wersji sed, zatem

Sed Linux Man Page

#Linux
sed -i"" 

I

Sed OSX man page

#OSX (notice the space after the '-i' argument)
sed -i "" 

I got round to w skrypcie za pomocą polecenia alias 'D i wyjścia nazwy systemu operacyjnego' uname 'w bash'if'. Próba przechowywania zależnych od systemu operacyjnego ciągów poleceń w zmiennych została zauważona i pominięta podczas interpretacji cudzysłowów. Użycie' shopt-s expand_aliases ' jest konieczne do rozszerzenia/użycia aliasów zdefiniowanych w skrypcie. korzystanie z shopt jest przedmiotem tutaj .

 6
Author: Big Rich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:26

Natknąłem się na ten problem. Jedynym szybkim rozwiązaniem było zastąpienie sed w mac na wersję gnu:

brew install gnu-sed
 1
Author: vikrantt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-20 21:47:58

Jeśli musisz wykonać sed in-place w skrypcie bash, a nie chcesz, aby wynik w in-place z .plików bkp, a Ty masz sposób na wykrycie systemu operacyjnego (powiedzmy, używając ostype.sh ), -- wtedy powinien zadziałać następujący hack z bash powłoką wbudowaną eval:

OSTYPE="$(bash ostype.sh)"

cat > myfile.txt <<"EOF"
1111
2222
EOF

if [ "$OSTYPE" == "osx" ]; then
  ISED='-i ""'
else # $OSTYPE == linux64
  ISED='-i""'
fi

eval sed $ISED 's/2222/bbbb/g' myfile.txt
ls 
# GNU and OSX: still only myfile.txt there

cat myfile.txt
# GNU and OSX: both print:
# 1111
# bbbb

# NOTE: 
# if you just use `sed $ISED 's/2222/bbbb/g' myfile.txt` without `eval`,
# then you will get a backup file with quotations in the file name, 
# - that is, `myfile.txt""`
 1
Author: sdaau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-02 11:22:32

Możesz użyć gąbki. Sponge jest starym programem uniksowym, znalezionym w pakiecie moreutils (zarówno w ubuntu i prawdopodobnie Debianie, jak i w homebrew na Macu).

Spowoduje buforowanie całej zawartości z potoku, odczekanie aż potok się zamknie (prawdopodobnie oznacza to, że plik wejściowy jest już zamknięty), a następnie nadpisanie:

Ze strony man :

Synopsis

Sed"..."plik / grep"...'/Sponge file

 0
Author: Guillermo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-06 13:16:50

Przenośny skrypt dla systemów GNU i OSX:

if [[ $(uname) == "Darwin" ]]; then
    SP=" " # Needed for portability with sed
fi

sed -i${SP}'' -e "s/foo/bar/g" -e "s/ping/pong/g" foobar.txt
 0
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-09 19:43:10

Na Linuksie i OS X działa Mi:

sed -i' ' <expr> <file>

Np. dla pliku f zawierającego aaabbaaba

sed -i' ' 's/b/c/g' f

Daje aaaccaaca zarówno na Linuksie, jak i Macu. Notatka zawiera cytowany łańcuch zawierający spację , z brak spacji pomiędzy -i a łańcuchem. Pojedyncze lub podwójne cytaty działają.

Na Linuksie używam bash wersji 4.3.11 pod Ubuntu 14.04.4 i na Mac wersji 3.2.57 pod OS X 10.11.4 El Capitan (Darwin 15.4.0).

 -1
Author: David G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-19 15:24:08