sed Mac (BSD) ve Linux üzerinde çalışan yerinde bayrak


237

sedHem Linux hem de Mac'te çalışan yedekler olmadan yapılacak yerinde düzenleme çağrısı var mı ? sedOS X ile gönderilen BSD'ye ihtiyaç sed -i '' …duyulsa da, GNU sedLinux dağıtımları genellikle tırnakları boş girdi dosyası adı (yedekleme uzantısı sed -i …yerine ) olarak yorumlar ve bunun yerine ihtiyaç duyar .

Her iki tat ile de çalışan herhangi bir komut satırı sözdizimi var mı, bu yüzden her iki sistemde de aynı komut dosyasını kullanabilir miyim?


Perl bir seçenek değil mi? Must Eğer sed kullanmak?
Noufal Ibrahim

Belki GNU sürümünü kurun ve kullanın! topbug.net/blog/2013/04/14/… ? İlk önce denerdim. Sonra tekrar, bu tür berbat.
Dmitry Minkovsky

2
@dimadima: OS X makinelerinde kırılan kişisel komut dosyaları olan bu soruya göz atan diğer bazı kişiler için ilginç olabilir. Benim durumumda, yine de, kullanıcıya GNU sed'i yüklemesini söylemenin, bu egzersizin orijinal amacını yeneceğini söyleyen bir açık kaynak projesinin derleme sistemine ihtiyacım vardı (birkaç dosyayı "her yerde çalışır" tarzında yama yapın) .
dnadlinger

@klickverbot evet, mantıklı. İlk olarak bir cevap olarak yorumu ekledim ve sonra sildim, sorunuzun bir cevabı olmadığını fark ettim :).
Dmitry Minkovsky

1
Çapraz referans: sed -i (yerinde düzenleme) ile taşınabilirlik nasıl elde edilir? Unix ve Linux Stack Exchange'de.
MvG

Yanıtlar:


212

Gerçekten sadece sed -i'kolay' yolu kullanmak istiyorsanız , aşağıdakiler hem GNU hem de BSD / Mac üzerinde çalışır sed:

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

Yer ve nokta eksikliğine dikkat edin.

Kanıt:

# 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

Belli ki .bakdosyaları silebilirsiniz .


2
Bu yol. Birkaç karakter ekleyin ve taşınabilir. Yedek dosyasını silmek önemsizdir (çağırırken dosya adına zaten sahipsiniz sed)
slezica

Bu mac üzerinde çalıştı, ancak ubuntu 16.04 orijinal dosya üzerine 0 bayt üzerine yazar ve aynı zamanda 0 bayt ile .bak dosyası oluşturur?
house9

1
Unutmayın, macOS Sierra'da (ve muhtemelen daha önce, kullanışlı bir makinem yok), çağrıldığında sedkonumsal bir commandargümanı kabul etmez -i- başka bir bayrakla birlikte verilmelidir-e . Böylece, komut şöyle olur:sed -i.bak -e 's/foo/bar/' filename
ELLIOTTCABLE

5
Bu özellikle yedeklemeler oluştururken, OP özellikle yerinde düzenleme ister.
Marc-André Lafortune

8
Yani tam çözüm:sed -i.bak 's/foo/bar/' file && rm file.bak
joeytwiddle

112

Bu GNU sed ile çalışır, ancak OS X'te çalışmaz:

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

Bu OS X üzerinde çalışır, ancak GNU sed ile çalışmaz:

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

OS X'te

  • kullanamaz sed -i -eyedekleme dosyasının uzantısı olarak ayarlanmalıdır olacağından-e
  • kullanamaz sed -i'' -earasında bir alana ihtiyacı aynı o-nedenleriyle -ive ''.

1
@AlexanderMills Bir sonraki argümanın bir komut olduğunu söyler - burada da atlanabilir.
Benjamin W.

4
Bunun -ive -i''kabuk ayrıştırma zamanında özdeş olduğunu unutmayın ; sed olamaz da aynı argümanları alır çünkü farklı bu iki birinci çağırmaları üzerine davranırlar.
wchargin

44

OSX'teyken, komut dosyalarındaki sorunları önlemek için GNU sed sürümünü her zaman Homebrew aracılığıyla yüklerim, çünkü çoğu komut dosyası GNU sed sürümleri için yazılmıştır.

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

Daha sonra BSD sed'iniz GNU sed ile değiştirilecektir.

Alternatif olarak, varsayılan adlar olmadan da yükleyebilirsiniz, ancak:

  • Yükledikten PATHsonra talimatlara uygun şekilde değiştiringnu-sed
  • Sisteminiz arasında gsedveya sedsisteminize bağlı olarak seçim yapmak için komut dosyalarınızı kontrol edin

4
--with-default-namesoldu homebrewleri-çekirdek çıkarılır , içinde fazla bilgi bu cevap. yüklerken gnu-sedşimdi, kurulum talimatları eklemek gerektiğini belirtmek gnubiniçin için PATH:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
pgericson

18

Noufal İbrahim'in dediği gibi , neden Perl kullanamıyorsunuz? Herhangi bir Mac Perl'e sahip olacak ve temel sistemde bazı Perl sürümlerini içermeyen çok az Linux veya BSD dağıtımı var. Aslında Perl'den yoksun olabilecek tek ortamdan biri BusyBox (GNU / Linux gibi çalışır -i, ancak yedekleme uzantısı belirtilemez).

As ismail , önerir

Perl her yerde mevcut olduğundan perl -pi -e s,foo,bar,g target.file

ve bu, sed -iGNU / Linux ve BSD / Mac arasındaki temel uyumsuzlukla başa çıkmak için komut dosyalarından, takma adlardan veya diğer çözümlerden daha iyi bir çözüm gibi görünüyor .


Bu çözümü seviyorum. perl1 Mayıs 2009 yılından beri Linux Standard Base özelliğinin bir parçası olan refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/...
OregonTrail

1
Bu kolayca taşınabilirlik için en iyi çözümdür
ecnepsnai

17

Çalışmasını sağlamanın bir yolu yok.

Bunun bir yolu aşağıdaki gibi geçici bir dosya kullanmaktır:

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

Bu her ikisinde de çalışır


SOME_FILE = "$ (sed -s" s / abc / def / "bazı / dosya)"; echo "$ SOME_FILE"> bazı / dosya; bunun yerine çalışmaz
Jason Gross

Bir bash değişkeninin maksimum boyutu ile sınırlı olacağınız anlaşılıyor, değil mi? GBs dosyalarıyla çalışacağından emin değilim.
analog

3
Geçici bir dosya oluşturuyorsanız, neden @kine'nin önerdiği gibi bir yedekleme dosyası oluşturmak için bir uzantı vermiyorsunuz (daha sonra kaldırabilirsiniz)?
Alex Dupuy

13

Cevap: Hayır.

Başlangıçta kabul edilen cevap aslında talep edilen şeyi yapmaz (yorumlarda belirtildiği gibi). (Bu cevabı file-edizinlerimde a'nın "rastgele" görünmesinin nedenini ararken buldum .)

Görünüşe göre almanın bir yolu yok sed -i hem MacOS hem de Linuces üzerinde sürekli çalışmanın bir .

Tavsiyem, değerinde olan şey için yerinde güncelleme yapmak değil sed(karmaşık hata modlarına sahip) değil, yeni dosyalar oluşturmak ve daha sonra yeniden adlandırmaktır. Başka bir deyişle: kaçının -i.


9

Bu -iseçenek POSIX Sed'in bir parçası değildir . Daha taşınabilir bir yöntem Vim'i Ex modunda kullanmak olabilir:

ex -sc '%s/alfa/bravo/|x' file
  1. % tüm satırları seç

  2. s değiştirmek

  3. x kaydet ve kapat


Bu doğru cevap. POSIX'in temel özelliği taşınabilirliktir.
Kajukenbo

9

İşte evalyedekleme dosyalarını silmek zorunda kalmadan ve Linux ve macOS üzerinde çalışan başka bir sürüm . sedParametreleri saklamak için , kullanmaktan daha temiz olan Bash dizilerini kullanır 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

Bu bir yedekleme dosyası oluşturmaz, ekli tırnak işareti içeren bir dosya oluşturmaz.


2
bu doğru cevap. Biraz sadeleştiririm, ama fikir mükemmel çalışıyor sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '') sed "${sedi[@]}" -e 's/foo/bar/' target.file
Alex Skrypnyk

İyi şeyler! Yine de okunabilirlik için daha uzun versiyonu tercih ediyorum.
nwinkler

1
Bu benim için farklı sistemlerle uyumlu olmanın en iyi yolu.
Victor Choy

6

Steve Powell'ın cevabı oldukça doğru, OSX ve Linux'ta (Ubuntu 12.04) sed için MAN sayfasına danışmak, iki işletim sisteminde 'yerinde' sed kullanımı içindeki uyumsuzluğu vurgular.

JFYI, sed'in Linux sürümünü kullanarak -i ve herhangi bir tırnak (boş dosya uzantısını gösteren) arasında boşluk olmamalıdır.

sed Linux Man Sayfası

#Linux
sed -i"" 

ve

sed OSX Man sayfası

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

Ben bir alias'd komut ve bir bash içinde ' uname ' OS-adı çıktısı kullanarak bir komut dosyası bu yuvarlak var . İşletim sistemine bağımlı komut dizelerini değişkenlerde depolamaya çalışmak, tırnakları yorumlarken vuruldu ve özlendi. Betiğinizde tanımlanan diğer adları genişletmek / kullanmak için ' shopt -s expand_aliases ' kullanılması gerekir. shopt kullanımı burada ele alınmaktadır .


1

sedBir bashkomut dosyasında yerinde yapmanız gerekiyorsa ve yerinde .bkp dosyalarıyla sonuçlanmasını istemiyorsanız ve işletim sistemini (örneğin, ostype.sh kullanarak ) algılamanız için bir yolunuz varsa , - bashkabuk yerleşik hack aşağıdaki evalçalışmalıdır:

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""`

0

Sünger kullanabilirsiniz. Sünger, moreutils paketinde (hem ubuntu'da hem de debian'da ve mac'taki homebrew'da) bulunan eski bir unix programıdır.

Borudaki tüm içeriği arabelleğe alır, boru kapatılıncaya kadar bekler (muhtemelen giriş dosyasının zaten kapalı olduğu anlamına gelir) ve ardından üzerine yazar:

Gönderen adam sayfası :

özet

sed '...' dosya | grep '...' | sünger dosyası


3
Hoş bir yaklaşım - ne yazık ki orijinal duruma gerçekten yardımcı olmuyor çünkü sed'e başvurmanın nedeni, istemci makinelerde kullanılan, platformdan başka bir şeye bağlı olamayacağınız bir platformlar arası yardımcı komut dosyasında kullanılacak bir şeylere sahip olmaktı. araçlar kuruluyor. Yine de başka birine yardımcı olabilir.
dnadlinger

0

Linux ve OS X'te aşağıdakiler benim için çalışıyor:

sed -i' ' <expr> <file>

örneğin, aşağıdakileri fiçeren bir dosya içinaaabbaaba

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

verimleri aaaccaacaLinux ve Mac üzerinde. Dize ile arasında boşluk olmayan , boşluk içeren tırnak içine alınmış bir dize olduğuna dikkat edin. Tek veya çift tırnak her ikisi de çalışır.-i

Linux'ta bashUbuntu 14.04.4 altında 4.3.11 sürümünü ve OS X 10.11.4 El Capitan (Darwin 15.4.0) altında Mac 3.2.57 sürümünü kullanıyorum.


1
Vay be, imkansız olduğunu ve okumaya devam ettiğini söyleyerek yukarıdaki herkesi dinlemediğime sevindim! Bu gerçekten işe yarıyor. Teşekkürler!
Personman

4
Mac OS'de benim için çalışmıyor ... dosya adının sonuna boşluk eklenmiş yeni bir dosya oluşturulur
Frédéric

Mac'te de benim için çalışmıyor (/ usr / bin / sed) - Artık dosya adına eklenmiş bir alana sahip fazladan bir yedek
dosyam var

Alanı tek tırnaklardan çıkarmaya çalış, benim için işe yarıyor.
dps

0

Bu sorunla karşılaştım. Tek hızlı çözüm, sed in mac'i gnu sürümüyle değiştirmekti:

brew install gnu-sed

Bu, mevcut bir cevabı 2015'ten çok daha fazla ayrıntıyla
çoğaltıyor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.