Mac ve Linux'ta metin dosyalarında yinelemeli arama ve değiştirme


127

Linux kabuğunda, aşağıdaki komut yinelemeli olarak tüm 'this' örneklerini 'that' ile arayacak ve değiştirecektir (önümde bir Linux kabuğum yok, ama olmalı).

find . -name "*.txt" -print | xargs sed -i 's/this/that/g'

OSX'te benzer bir komut neye benzeyecek?


apple.stackexchange.comLinux veya tüm geliştiriciler için yeterince genel olmadığından, muhtemelen taşınmalıdır .
AlikElzin-kilaka

Yanıtlar:


246

OS X, BSD ve GNU araçlarının bir karışımını kullanır, bu nedenle en iyisi her zaman belgeleri kontrol edin (yine lessde OS X kılavuzuna uymayan bile olsa):

https://web.archive.org/web/20170808213955/https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/sed.1.html

sed, -iyedeklemelerin uzantısı olarak sonra argümanı alır . -i ''Yedekleme yapılmaması için boş bir dize ( ) sağlayın .

Aşağıdakiler yapmalıdır:

LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +

Bu -type fsadece iyi bir uygulamadır; ona bir dizin verirseniz sed şikayet eder. -exectercih edilir xargs; -print0herhangi bir şeyle uğraşmanıza gerek yok . {} +Uç araçlarının en findyerine denilen komuta tek bir örnek olacak argümanlar gibi tüm sonuçları ekler Her sonuç için onu yeniden çalışan. (Bir istisna, işletim sistemi tarafından izin verilen maksimum sayıda komut satırı argümanının ihlal edilmesidir; bu durumda findbirden fazla örnek çalıştırılır.)


2
Bu ikamedeki "bu", bir eğik çizgi (localhost / site) içeriyor - .html dosyasında bir URL'nin parçalarını değiştiriyorum .... böyle bir ikameyi nasıl yaparım. Çift tırnak işareti koymayı denedim ama başarısız oldu.
Timothy T.

6
Sed sözdizimi , bölü çizgisi yerine hemen hemen her karakterin kullanılmasına izin verir , örneğin %: karakterini kullanabilirsiniz sed "s%localhost/site%blah/blah%". Başka bir alternatif ayırıcısını kullanılan karakterler-kaçış etmektir: sed "s/localhost\/site/blah\/blah/".
TaylanUB

Teşekkürler deneyeyim. Bununla birlikte eğik çizgiyi ayırmak için {} kullanmayı denedim ve hala bir hata alıyorum ...
Timothy T.

16
Başka illegal byte sequencehata alan var mı? eğer öyleyse, deneyin: LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +benim için çalıştı.
ColdTuna

10
Bu sadece bir dosya başına ocurreny, kullanımı yerini alacak /ggibi birden ocurrencies içinLC_ALL=C find . -type f -exec sed -i '' s/search/replace/g {} +
jamesjara

153

Mac için daha benzer bir yaklaşım şu olacaktır:

find . -name '*.txt' -print0 | xargs -0 sed -i "" "s/form/forms/g"

10
Keşke her geri döndüğümde ve onu kullandığımda bunu yükseltebilseydim. Şimdiye kadar +15 olur, kolay.
Droogans

Nedense benim için çalışmıyor. Hiçbir şey yapmaz. Form360 klasörünün içindeyim ve easyform adıyla tüm dize örneklerini form360 olarak değiştirmeye çalışıyorum, aşağıdaki komutu çalıştırıyorum:find . -name '*.php' -print0 | xargs -0 sed -i "" "s/easyform/form360/g"
Andres Ramos

2
benim için bu doğru cevap olmalı. Benim için çalışan tek kişi oydu.
nosequeldeebee

1
-print0 | xargs -0, dosya adı boşluk içerdiğinde mac'imde çalışmıyor.
user2807219

1
sed:.: yerinde düzenleme yalnızca normal dosyalar için çalışır
codlapper

14

Alternatif bir çözüm olarak, bunu Mac OSX 10.7.5'te kullanıyorum

grep -ilr 'old-word' * | xargs -I@ sed -i '' 's/old-word/new-word/g' @

Kredi: Todd Cesere'nin cevabı


Bu iyi çalışıyor! Diğer komut dosyaları, OSX'te bazı durumlarda fazladan bir satır sonu ekler! Çok teşekkürler!
Sebastien Filion

14

Mac OSX 10.11.5'te bu gayet iyi çalışıyor:

grep -rli 'old-word' * | xargs -I@ sed -i '' 's/old-word/new-word/g' @

xargs -I @ sed -i '' 's / eski-kelime / yeni-kelime / g' @ pek çok çalışmayan öneriyi denedikten sonra benim için çalıştı. Teşekkür ederim!
DrB

13

Yukarıdakilerin hiçbiri OSX üzerinde çalışmaz.

Aşağıdakileri yapın:

perl -pi -w -e 's/SEARCH_FOR/REPLACE_WITH/g;' *.txt

1
SEARCH_FOR ve REPLACE_WITH yol ise '/' nasıl taranır?
rraallvv

Farklı bir sınırlayıcı kullanın. Yol kullanıyorsanız, iki nokta üst üste veya boru işe yarar. örneğin 's | ARA | DEĞİŞTİR | g'. 'S {SEARCH} {REPLACE}' içinde olduğu gibi kullanımımız parantez.
dannysauer

1
dito sorusu, Mac'te hayır denemek - ama bir hata oluşturuyor gibi görünüyor? Örneğin, yolum bir dosya olarak yorumlanıyor? -bash: nohost localhost /: Böyle bir dosya ya da dizin
Timothy T.

bu derin klasörlerde yinelenmez. Sadece bir seviye.
Sergey Romanov

Bu komut hakkında daha fazla bilgi için bu lifehacker.com/5810026/… 'i
kuzdu

7

Hem Linux hem de Mac OS X üzerinde çalışan bir sürüm ( -eanahtarı ekleyerek sed):

export LC_CTYPE=C LANG=C
find . -name '*.txt' -print0 | xargs -0 sed -i -e 's/this/that/g'

Dışa aktarımı bu yanıttan + kabul edilen yanıttan gelen satırı yapmak zorunda kaldım (yedek dosyaların oluşturulmasını istemedim)
Lance

2
'geçersiz bayt dizisi' hatasını export LC_CTYPE=C && export LANG=C
adreslemek için

Git kullanıyorsanız benim yaptığım gibi bunu '* .filetype' yerine '*' ile ÇALIŞTIRMAYIN. Veya yayınlanmamış tüm çalışmalarınıza veda edebilirsiniz.
Sergey

1
Sed komutunun mac sürümü -i'den sonra bir '' gerektirir, bu nedenle bu cevap yanlıştır
G Huxley

2

Bu komutu ne zaman yazsam her zaman hortumla dolduruyor veya bir bayrağı unutuyorum. TaylanUB'un cevabından yola çıkarak github'da bir Gist oluşturdum ve mevcut dizinden genel bir bulma değişikliği yapıyor. Bu, Mac OSX'e özgüdür.

https://gist.github.com/nateflink/9056302

Güzel, çünkü şimdi bir terminal açıp sonra kopyaladım:

curl -s https://gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "bul-a-url.com" "değiştir-a-url.com"

Bazı garip bayt dizisi hataları alabilirsiniz, işte tam kod:

#!/bin/bash
#By Nate Flink

#Invoke on the terminal like this
#curl -s https://gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

if [ -z "$1" ] || [ -z "$2" ]; then
  echo "Usage: ./$0 [find string] [replace string]"
  exit 1
fi

FIND=$1
REPLACE=$2

#needed for byte sequence error in ascii to utf conversion on OSX
export LC_CTYPE=C;
export LANG=C;

#sed -i "" is needed by the osx version of sed (instead of sed -i)
find . -type f -exec sed -i "" "s|${FIND}|${REPLACE}|g" {} +
exit 0

2

Bu benim uygulanabilir olanım. mac OS X 10.10.4'te

grep -e 'this' -rl . | xargs sed -i '' 's/this/that/g'

Yukarıdaki olanlar kullanmak find ayrıntılı bir arama metni (dosya sonuna yeni bir satır ekleyin) içermez dosyaları değişecektir.


2

Bir zsh terminali kullanıyorsanız, joker karakter sihrini kullanabilirsiniz:

sed -i "" "s/search/high-replace/g" *.txt


1

Bu biçimi kullandım - ama ... Son derece garip bulduğum her örneği gerçekten değiştirmek için onu üç veya daha fazla kez çalıştırmam gerektiğini fark ettim. Bir kez çalıştırmak her dosyada bazılarını değiştirir, ancak hepsinde değil. Tam olarak aynı dizeyi iki-dört kez çalıştırmak tüm örnekleri yakalar.

find . -type f -name '*.txt' -exec sed -i '' s/thistext/newtext/ {} +

Bu komutu birden çok kez çalıştırmanız gerekiyordu g, çünkü sed regex'inizin sonunda a'ya ihtiyacı var , aksi takdirde yalnızca thistextbir satırdaki ilk geçtiği yerin yerini alır . Yani normal ifadeniz şöyle olmalıdırs/thistext/newtext/g
Les Nightingill

0

https://bitbucket.org/masonicboom/serp , OSX üzerinde test edilmiş, belirli bir dizindeki dosyalardaki metinler için yinelemeli arama ve değiştirme yapan ve her bir değişikliği onaylayan bir go yardımcı programıdır (yani çapraz platform). Yeni, buggy olabilir.

Kullanım şöyle görünür:

$ ls test
a  d  d2 z
$ cat test/z
hi
$ ./serp --root test --search hi --replace bye --pattern "*"                         
test/z: replace hi with bye? (y/[n]) y
$ cat test/z
bye


-3

OSX'teki komut, güzel kullanıcı arayüzündeki Unix ile tamamen aynı olmalıdır.


Ben de öyle düşündüm, ama hayır. Sed'e beslenirken dosyaların önüne bir ./ koyar, bu yüzden sed "geçersiz komut kodu" ndan şikayet eder. Belki sadece yorgunum ;-)
Jack

@JacobusR, lütfen OSX terminalinizden kesip yapıştırın - biraz farklı bir şey giriyor olmalısınız.
glenn jackman

3
Sen isteyebileceğiniz -print0ilave findbayrakları ve -0karşı xargsbayraklar.
jmtd

Ayrıca xargs -exec sed -i s/this/that/g {} \+yerine de kullanabilirsiniz-print
Marian

@JacobusR - bu, önde gelen './' yol adı olsa bile çalışır. Bununla birlikte, dosya adında bir boşluk varsa, "./jacobus \ R.txt" deyin, kullanımı xargs, alanla sınırlanmış "./jacobus" dosyasını aktarılacak bir dosya olarak sedve ardından "R.txt" ile görebilir. hiçbiri yok.
Brett Hale

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.