sed komutuyla -i seçeneği Mac'te başarısız oluyor, ancak Linux'ta çalışıyor


303

sedLinux'ta metin aramak / değiştirmek için aşağıdaki komutu başarıyla kullandım :

sed -i 's/old_link/new_link/g' *

Ancak, Mac OS X'imde denediğimde:

"c komutu bekliyor \ ve ardından metin"

Mac'imin normal bir BASH kabuğu çalıştırdığını düşündüm. Naber?

DÜZENLE:

@High Performance'a göre, bu Mac'in sedfarklı (BSD) bir lezzete sahip olmasından kaynaklanıyor, bu yüzden sorum bu komutu BSD'de nasıl çoğaltırım sed?

DÜZENLE:

İşte buna neden olan gerçek bir örnek:

sed -i 's/hello/gbye/g' *

1
Bu sed, verilerinizde bir "c" yi komut olarak göreceği anlamına gelir . Değişken mi kullanıyorsunuz? Lütfen gerçek komutu ve işlediğiniz bazı verileri daha yakından temsil eden bir şey gönderin. Bu hatayı basit bir şekilde göstererek yapabilirsiniz echo x | sed c.
sonraki duyuruya kadar duraklatıldı.

@Dennis, yukarıdaki basit komut buna neden oluyor, ancak işlediği veriler html ve css dosyaları da dahil olmak üzere tüm bir web sitesi (tüm resim bağlantılarını dönüştürüyorum) olsa da ...
Yarin

Yanıtlar:


397

-iSeçeneği kullanırsanız, yedeklemeleriniz için bir uzantı sağlamanız gerekir.

Eğer varsa:

File1.txt
File2.cfg

Komutu (arasındaki boşluk eksikliği dikkat -ive ''ve -ebunun Mac ve GNU yeni sürümlerinde çalışması için):

sed -i'.original' -e 's/old_link/new_link/g' *

Aşağıdaki gibi 2 yedek dosya oluşturun:

File1.txt.original
File2.cfg.original

Her durumda çalışan sed komutlarının bir karışımını bulmak imkansız olduğu için yedekleme dosyaları yapmaktan kaçınmanın taşınabilir bir yolu yoktur:

  • sed -i -e ...- -eyedeklemeler oluşturduğundan OS X üzerinde çalışmaz
  • sed -i'' -e ... - OS X 10.6'da çalışmaz, ancak 10.9+ üzerinde çalışır
  • sed -i '' -e ... - GNU üzerinde çalışmıyor

Not Tüm platformlarda çalışan bir sed komutu olmadığından, aynı sonucu elde etmek için başka bir komut kullanmayı deneyebilirsiniz.

Örneğin, perl -i -pe's/old_link/new_link/g' *


4
Aynı sorunu yaşadım. Bu çözüm için teşekkürler. Ama '-i' tanımını bulmak için 'man sed' ile çalıştığım yerde, -i '' yi kullanmak için yedekleri görmezden gelmekle ilgili hiçbir şey yok. Bu benim ilk suçum. İkincisi, "komut bekliyor \ ve ardından metin" hatası ortaya çıktığında, neden doğrudan '-i' seçeneği için bir yedekleme adı beklediğini bize söylemiyor? Böyle bir şey her yerde olur: bir hata alırsınız, ancak hatanın nedenini değil, o zaman bunun hakkında hiçbir şey açıklamayan kılavuzu ararsınız. Sonra başka birinin de aynı sorunu bulmak için google. Yani, neden kılavuzda örnek vermiyorsunuz?
lukmac

ya da bir hatanın oluştuğunu sadece bilgi içermeyen bir mesaj yerine hatanın neden olduğunu bize bildirin. Bu yorumu okuyabildikleri takdirde, bu durum tüm araç üreticileri için bir öneridir.
lukmac

5
@lukmac Anlayabildiğim kadarıyla sedbir yedek sonek sağladınız . Yedekleme soneki s/old_link/new_link/g. Bundan sonraki argümanın düzenleme komutları olması gerekiyordu. Komutları yedekleme adı olarak yorumladığından, ilk dosya adını düzenleme komutları olarak aldı, ancak bunlar geçerli değildi.
Mart'ta Barmar

2
Bu her zaman bir sorun olacak mı? Apple'ın OSX ile bir geçici çözüm / paket GNU sed oluşturabilmesinin bir yolu var mı? Veya GNU sed destekleyemedi sed -i '' -e ...mi?
blong

5
sed -i'' -emac 10.14
MoOx


55

Bu sed'in GNU ve BSD sürümleriyle çalışır:

sed -i'' -e 's/old_link/new_link/g' *

veya yedekli:

sed -i'.bak' -e 's/old_link/new_link/g' *

-iSeçenek sonra boşluk eksik unutmayın ! (GNU sed için gereklidir)


7
Birincisi OSX üzerinde çalışmıyor (10.6.8'de test ettim)
marcin

4
Benim için OS X (10.10.3) üzerinde, ilki -e ile eklenmiş yedek dosyalar oluşturdu. İyi değil. İkincisi, Ubuntu ve OS X arasında sürekli olarak benim için çalışan tek şeydi. Yedek dosyaları olsa da istemedim, bu yüzden rmsilmek için hemen sonra bir komut çalıştırmak zorunda kaldım .
Brendan

1
İlk satır, 10.10: sed -i'' ...=>sed -i '' ...
Daniel Jomphe

3
@DanielJomphe Ama bu alanı eklemek GNU sed üzerinde çalışmıyor
Brice

1
@marcin ilki OSX 10.11.2'de de benim için çalışıyor. Tek şey, daha sonra kaldırılması gereken bir yedekleme dosyası oluşturmasıdır. İkincisi daha iyi görünüyor, çünkü daha sonra dosya adını bulmamız gerekmiyor.
17:03

41

Mac'te de aynı sorunu yaşadım ve çözdüm brew:

brew install gnu-sed

ve olarak kullan

gsed SED_COMMAND

için seddiğer ad olarak da ayarlayabilirsiniz gsed(isterseniz):

alias sed=gsed

3
Neden tam olarak verdin aynı cevabı olarak Ohad Kravchick ?
gniourf_gniourf

1
böyle bir takma ad ayarlamak harika bir fikir değil
SantaXL

1
Karşılık gelen demleme sayfasında önerildiği gibi bir takma ad yerine, yolu bu yola ekleyin: PATH = "$ (demlemek --prefix) / opt / gnu-sed / libexec / gnubin: $ PATH"
y.luis

24

Ya da sed'in GNU sürümünü Mac'inize gsed adlı olarak yükleyebilir ve standart Linux sözdizimini kullanarak kullanabilirsiniz.

Bunun için, gsedbağlantı noktalarını kullanarak yükleyin (yoksa, http://www.macports.org/ adresinden ) sudo port install gsed. Sonra koşabilirsinsed -i 's/old_link/new_link/g' *


24
..veya homebrew kullanıyorsanız, o zaman yükleyingnu-sed
Sudar

1
Teşekkürler @Sudar, çift başparmak yukarıya!
Andrew Swan

9

Mac'iniz gerçekten bir BASH kabuğu çalıştırıyor, ancak bu daha çok hangi sed ile uğraştığınızla ilgili bir soru. Bir Mac sed'de BSD'den gelir ve tipik bir Linux kutusunda bulabileceğiniz sed'den oldukça farklıdır. Sana öneririm man sed.


3
BSD sorununa işaret ettiğiniz için teşekkür ederiz - Ama oldukça okuryazar değilim ve sadece komutum için hızlı bir düzeltmeye ihtiyacım var - adama hızlı bakış bana hiçbir şey söylemiyor
Yarin

5
@Yarin - hayır ve adam sed'e hızlı bir bakış atarsam, bu da size bir şey söylemez. Daha uzun bir bakış deneyin.
Yüksek Performanslı Mark

21
Çoğu SO yanıtı bir erkekte bir yere gömülüdür, ancak SO'nun akıllı insanlardan yanıt alması gereken yoğun insanlar budur
Yarin

9

Sinetris'in cevabı doğrudur, ancak findhangi dosyaları değiştirmek istediğim konusunda daha kesin olmak için bunu komutla kullanıyorum . Genel olarak bu çalışmalıdır (osx üzerinde test edilmiştir /bin/bash):

find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \;

Genel olarak karmaşık projelerde sedolmadan kullanıldığında finddaha az verimlidir.


-execçok güzel! Sadece sonunda eğik çizginin gerçekten gerekip gerekmediğini merak ediyorum
Ye Liu

2
@YeLiu: olmadan \, ;böyle çalışınca kabuk tarafından yorumlanır var
inc serv-

2

sedMacOS (MacOS 10.12'de test edilmiştir) ve diğer işletim sistemleri arasındaki farkı işlemek için bir işlev oluşturdum :

OS=`uname`
# $(replace_in_file pattern file)
function replace_in_file() {
    if [ "$OS" = 'Darwin' ]; then
        # for MacOS
        sed -i '' -e "$1" "$2"
    else
        # for Linux and Windows
        sed -i'' -e "$1" "$2"
    fi
}

Kullanımı:

$(replace_in_file 's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' "./mysql/.env")

Nerede:

, bir sınırlayıcı

's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' kalıp

"./mysql/.env" dosya yolu


1

Ortam değişkenlerini şablon dosyasına nasıl uygulayacağınız aşağıda açıklanmıştır (yedekleme gerekmez).

1. Daha sonra değiştirmek için {{FOO}} ile şablon oluşturun.

echo "Hello {{FOO}}" > foo.conf.tmpl

2. {{FOO}} yerine FOO değişkeni koyun ve yeni foo.conf dosyasına gönderin

FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf

Çalışma hem MacOS 10.12.4 ve Ubuntu 14.04.5


0

Diğer cevapların belirttiği gibi, yedek dosyaları yapmadan OS X ve Linux'ta taşınabilir bir şekilde sed kullanmanın bir yolu yoktur. Bunun yerine, bu Ruby one-liner'ı bunun için kullandım:

ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml

Benim durumumda, bir rakegörevden (yani, bir Ruby betiğinin içinde) çağırmak gerekiyordu , bu yüzden bu ek tırnak seviyesini kullandım:

sh %q{ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml}

-1
sed -ie 's/old_link/new_link/g' *

Hem BSD hem de Linux üzerinde çalışır


3
Bu, linux üzerine eeklenmiş başka bir dosya adı oluşturur
Brice

1
Kırık, çıkarmak daha iyi.
sorin

Mac ve Linux üzerinde çalışıyor. Bu çözümün sorunu nedir?
Islam Azab

Hayır, Mac BSD Sed üzerinde çalışmaz - dosya adına 'e' eklenmiş bir yedekleme dosyası oluşturur.
Jesper Grann Laursen
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.