Perl yapmanın bir yolu var mı?


12

Bir arkadaşım şunu yapar:

perl -pi.bak -e 's/foo/bar/' somefile

"somefile" aslında bir sembolik bağlantı olduğunda, perl sadece dokümanların ne yapacağını söyler:

Bunu, giriş dosyasını yeniden adlandırarak, çıktı dosyasını orijinal adıyla açıp print () deyimleri için varsayılan olarak bu çıktı dosyasını seçerek yapar. Uzantı, sağlanmışsa, yedek kopya oluşturmak için eski dosyanın adını değiştirmek için kullanılır [...]

Bu da değişmeyen gerçek dosyayı işaret eden yeni bir simge "somefile.bak" ve değişikliklerle birlikte yeni, değiştirilmiş normal dosya "somefile" ile sonuçlanır.

Birçok durumda, sembolik bağlantıyı izlemek istenen davranış olacaktır (.bak dosyasının doğru konumunu belirsiz bıraksa bile). Bunu bir sarmalayıcıdaki sembolik bağları test etmekten ve kasayı uygun şekilde işlemekten başka basit bir yol var mı?

( sedaynı şeyi, değerinde olan için yapar.)


1
Vim veya emacs çağırın (her ikisinin de simgeleri takip ettiğini düşünüyorum)? Cidden, cevabın -p -isenaryonuzda yeniden uygulanmasından korkuyorum .
Gilles 'SO- kötü olmayı bırak'

Sed aslında aynı şeyi yapmaz, en azından 4.2.1 sürümünden beri, 2009 yılının Haziran ayında yayınlanmamıştır. ; Bunun eski davranışa bağlı olabilecek mevcut komut dosyalarının bozulmasını önlemek için yapıldığını varsayıyorum.
Garrett

Yanıtlar:


6

Ben küçük olup olmadığını merak spongegenel amaçlı bir sistemdir ( "bir dosyaya standart girdi ve yazma içinize") elde moreutils bu durumda yardımcı olacak ve bunun sembolik takip edip.

Yazar şöyle tarif eder sponge :

Dosyaları Unix araçlarıyla yerinde düzenleme sorununu giderir, yani çıktıyı düzenlemeye çalıştığınız dosyaya yeniden yönlendirirseniz, yönlendirmenin ardışık düzendeki ilk komuttan önce yürürlüğe girmesi (dosyanın içeriğini tıkama) dosyadan okumaya döner. Bunun gibi geçiş yapar sed -ive perl -ibunun etrafında çalışır, ancak bir boru hattında kullanmak isteyebileceğiniz her komutun böyle bir seçeneği yoktur ve bu yaklaşımı zaten çok komutlu boru hatları ile kullanamazsınız.

Normalde biraz sünger kullanıyorum:

sed '...' file | grep '...' | sponge file

Hey, bu işe yarıyor. Gilles'in yukarıdaki yorumunun "gerçek" cevap olduğundan şüpheleniyorum, ancak cevap olarak yapmadığı için ve yeni bir yardımcı program öğrendiğimden beri bunu alacağım. :)
mattdm 16:11

Ama spongepratikte böyle bir kullanım için test yaptınız mı? Bana gelince: henüz değil. Lütfen burada istenen şekilde bir testte davranıp davranmadığını belirten bir yorum bırakabilir misiniz? Oh, yorumu görüyorum. Onay için teşekkürler!
imz - Ivan Zakharyaschev

- evet, cevap vermeden önce denedim. Ne zaman filesenin yukarıdaki örnekte sembolik köprü ise, bağlantı yalnız bırakılır ve gerçek dosya değişti.
mattdm

@mattdm: Evet, onay için teşekkürler! (
Yorumumu

3

somefileBir symlink olan bir gerçeği biliyorsanız , dosya için tam yolu aşağıdakilerle açıkça sağlayabilirsiniz:

perl -pi.bak -e 's/foo/bar/' $(readlink somefile)

Bu şekilde, değiştirme şimdi doğrudan orijinal dosyayla yapıldığından orijinal symlink bozulmadan kalır.


Ancak çıktısı readlinkyine başka bir sembolik olabilir. En kullanmak olacaktır -fya -eMüsait veya zsh'ler $file:Pveya (:P)eleme topak @ikegami gösterdiği gibi sembolik içermeyen yolunu almak için.
Stéphane Chazelas

3

Tek bir dosyayla uğraşıyorsanız, komut aşağıdaki gibi görünecektir:

perl -i -pe'...' -- "$qfn"

O zaman çözüm şudur:

perl -i -pe'...' -- "$( readlink -e -- "$qfn" )"

Bu hem sembolik hem de sembolik olmayan bağları ele alır.


İsteğe bağlı olarak çok sayıda dosyayla uğraşıyorsanız, komut aşağıdaki gibi görünür:

... | xargs -r perl -i -pe'...' --

O zaman çözüm şudur:

... | xargs -r readlink -ze -- | xargs -r0 perl -i -pe'...' --

Bu hem sembolik hem de sembolik olmayan bağları ele alır.


Uyarı readlink standart bir komut değildir, bu yüzden varlığı, bağımsız değişkenleri ve işlevselliği sisteme göre değişir, bu nedenle belgelerinizi kontrol ettiğinizden emin olun. Örneğin, bazı uygulamalarda vardır -f(burada da kullanabilirsiniz) -e, bazıları da yoktur. busybox's readlink -fGNU gibi davranır readlink -e. Ve bazı sistemler realpathbunun yerine readlinkgenellikle GNU gibi davranan bir komuta sahiptir readlink -f.

GNU ile readlink -emevcut bir dosyaya çözümlenemeyen sembolik bağlantıların sessizce kaldırıldığını unutmayın.


@ Stéphane Chazelas, $var:Pbenim için çalışmıyor. ( X='tmp' zsh -c 'perl -E"say for @ARGV" $X:P'çıktı tmp:P)
ikegami

için zsh 5.3 (2016) veya üstü gerekir $var:P. Daha eski sürümlerde, $var:Abunun yerine her zaman kullanabilirsiniz . Farklılıklar için kılavuza bakın ve tanıtmak için mantıksal bilgi için zsh.org/mla/users/2016/msg00593.html:P (gerçek realpath()arayüz).
Stéphane Chazelas

( :A4.3.10 (2009), GNU readlink -z2012'de eklendi, readlinkdestekleyen başka bir uygulamanın farkında değilim -z). GNU ile xargs, -rgirişin boş kalmayacağını garanti edemezseniz genellikle bu seçeneği istediğinizi unutmayın. Burada, önemli değil ( perlkod bir BEGIN/ ENDifadesi içermiyorsa ), -i used with no filenames on the command line, reading from STDIN.bu durumda bir uyarı alırsınız .
Stéphane Chazelas

Üzgünüz, -rbelgelerini yanlış okudum . Yaptıklarının tersini yaptığımı sanıyordum. Readded.
ikegami
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.