OSX ekini belirli bir satıra atar


24

Bu yüzden bir süredir linux üzerinde 'sed' kullanıyorum, ancak 'POSIX sed' ve 'GNU sed' çok küçük farklılıkları olduğundan OSX'te kullanmakta zorlanıyordum. Şu anda, belirli bir satır numarasından sonra bir satırlık metin eklemek için uğraşıyorum. (bu durumda, satır 4)

Linux'ta böyle bir şey yapardım:

sed --in-place "4 a\  mode '0755'" file.txt

Öyleyse OSX'te şunu denedim:

sed -i "" "4 a\ mode '0755'" file.txt

Ancak bu bana bir 'komutun sonunda \ sonra \' ekstra karakter 'hatası veriyor. Burada yanlış olan ne, fikrin var mı? Yazım hatası var mı? Yoksa sed sürümleri arasındaki başka bir farkı anlamıyor muyum?


2
MacOS 10.6.8'de çalışmadığını onaylayabilir. Debian 6.0.3'te düzgün çalışır.
tink

Yanıtlar:


24

Kesin konuşursak, POSIX şartnamesi aşağıdakilerdensed sonra yeni bir satır gerektirir a\:

[1addr]a\
text

Önceden tanımlandığı gibi standart çıktıya metin yazın.

Bu bir gömlekler muhtemelen aşağıdaki sebebi olan bir ağrı biraz, yazma yapar GNU uzantısı için a, ive ckomutları:

Bir GNU uzantısı olarak, anewline ile boşluk arasında başka bir boşluk \varsa, bu satırın metni, boşluktan sonraki ilk boşluk olmayan karakterden başlayarak a, metin bloğunun ilk satırı olarak alınır . (Bu tek satırlık bir eklenti komut dosyası yazarken basitleştirmeyi sağlar.) Bu uzantı ayrıca ive ckomutlarıyla da çalışır .

Bu nedenle, sedsözdiziminizde taşınabilir olmak için, bir a\şekilde yeni bir satır eklemeniz gerekir . En kolay yol, bir alıntı yeni satır eklemek için:

$ sed -e 'a\
> text'

(nerede $ve >kabuk istemleri). Bir acı bulursanız, bash[1], $' 'C tarzı çıkışlardan kaçmak için alıntı sözdizimine sahiptir;

sed -e 'a\'$'\n''text'

[1] ve mksh (r39b +) ve bazı bash olmayan bururne mermileri (örneğin, FreeBSD 9+ içerisinde / bin / sh)


Çok bilgilendirici cevap. Kesin alıntı sözdizimi ipucu için teşekkür ederiz.
cjackson,

14

Bu cevapta açıklandığı gibi i, açoklu komutlar gibi sed komutlarını kullanırken ve bunları kullandığınızda yardımcı olur -e "...". Bu fıkraların her birinin yeni satırlarla ayrıldığı anlaşılacaktır. iVe akomutlar satır içi (kullandıkları çağrılan bir çok satırlı sed komut dosyası kullanılmak üzere tasarlanmışlardır aksi komut dosyalarını sed kullanmak zordur sed -f file ...). Eklenecek metnin satırını ve satırını -eayırmak için bir cümlenin sonunda getirilen örtük newline'ı kullanamazsınız gibi görünüyor a\. Ancak, eklenecek metin satırını sonlandırmak için kullanabilirsiniz.

Bu özel durumda, yapmaya çalıştığınız şey aslında tek bir -e ...maddeyle gerçekleştirilebilir. Sadece akomutu doğru kullanmalısın . POSIX standardına göre, aa ile takip edilmeli \, ardından yeni bir satır takip etmeli, sonra bir sonraki satırın geri kalanı eklenecektir (yeni bir satıra veya maddenin sonuna kadar -e). Yani yapabilirsin:

sed -i "" -e $'4 a\\\n'"mode '0755'" file.txt

2
Hangi özellikleri kullanmakta olduğunuzun Gnu- isms olduğunu belirlemek istiyorsanız, bu sayfa yardımcı olabilir: wiki.alpinelinux.org/wiki/Regex . Ancak, yalnızca regex özellikleriyle sınırlıdır; diğer sed komutları değil.
dubiousjim

5

GNU sed, yine de kullandığım örneklere / öğreticilere dayanarak POSIX sed'den çok daha yaygın olarak kullanılıyor gibi görünüyor.

Kullandığım herhangi bir OSX makinesine GNU sed'i kurmanın çok daha kolay olduğunu öğrendim. İlgileniyorsanız, bunu yapmanın en iyi yolu Homebrew aracılığıyla yüklemektir .

Sadece $ brew install gnu-sedya da tüm ortak GNU yardımcı programlarını kullanabilirsiniz $ brew install coreutils.

Sonra sözdizimi sorunuyla dateveya başka bir programla karşılaştığınızda, yalnızca GNU sürümünü kullanabilirsiniz. Sonunda GNU sürümlerini her zaman kullanmanın ve bunları sistemimdeki sürümlerden daha erken koymanın daha kolay olduğuna karar verdim PATH.


5

Perl, böyle bir platform bağımlı GNU'ya karşı - GNU'ya karşı olmayan - "özel" deyimlerden zarar görmez. Yapabilirsin:

perl -ni.old -e 'print;if ($.==4) {print "mode 0755\n"}' file

-n' option creates a loop that reads every line of the input file. Unlike its cousin-P (not used here) it doesn't automatically print every line read. The-i invokes in-place replacement. The argument to-i (viz. ".old") can be dropped or changed. It leaves a backup of the unmodified file. The -ekomut başlangıcını işaret eder.

$.Hat-1 ile başlayan hat sayısını göstermektedir. Böylece komut satırı 'file' okur ve satır numarası 4'e eşit olduğunda, o satırın ardından ne enjekte etmek istersen onu yazdırır.

Perl’in köklerini sedAWK ve C’ye borçlu olduğunu eklemeye acele edeceğim , bu yüzden basit ikame sözdizimi vb. Çok dik bir öğrenme eğrisi değildir.


Güzel cevap! Ama biraz basitleştirebilirsin. Bu deneyin: perl -wlpi.old -e 'print "mode 0755" if $. == 5' file.txt. -p(Biz her satırı yazdırmak istediğiniz beri) anahtarı burada iyi çalışır; mantığı " satır 4'ten sonra yazdır" dan " satır 5'ten önce yazdır" a değiştirmeliyiz. Ve -lanahtarı "\ n" otomatik olarak her basılmış şekilde yapar printkendiniz yazdırmak zorunda kalmamak.
JL
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.