Gizemli bir şekilde başarısız olan sekmelerin basit sed değişimi


43

Bu gerçekten basit olmalı, ama nedense işe yaramadı:

sed -i.bak -E 's/\t/  /' file.txt

Sekme karakterlerini değiştirmek yerine tkarakterleri değiştiriyor . Düşünebildiğim, alıntı yapmak gibi oynayabileceğim her çeşitliliği denedim. Googled ve herkesi de benzer ifadeler kullanarak buldum ve onlar için çalışıyor gibi görünüyor.

Bu -Ebir OS X olayıdır. Başarısızlığın OS X’lerin tuhaf bir tuhaflığının sonucu olabileceğini düşündüm sed, bu yüzden Ruby ile de (onsuz -i) denedim ve aynı sonucu aldım:

ruby -pe '$_.gsub!(/\t/,"  ")' < file.txt > file.new

OS X ve Basherm'de Bash 3.2.51 kullanıyorum, ancak bunların ne kadar korkunç bir şekilde alakalı olabileceğini göremiyorum. Tuhaf bir ortam değişkeni ayarlamamıştım, ancak alakalı olabileceğini düşündüğün herhangi bir şeyi gönderebilirim.

Neyin yanlış olabilir?

GÜNCELLEME : Ruby versiyonunu denediğimde başka bir hata veya yazım hatası yapmış olmalıyım, çünkü Gilles bunun işe yaradığını işaret ediyor(ve beni asla yanlış yönlendirmedim!). Ne olduğundan emin değilim, ama benim hatam olmalı.


5
Değiştirmeye çalışmalısınız olabilir \tde sedsahip açıklamada CTRL-V<TAB>nerede <TAB>sekme anahtar ve CTRL-Vkumanda anahtarı ve bir varaya bastırdı.
— unxnut

Ruby de yanlış cevap alıyorsa, regexp kütüphaneniz olabilir. (Her iki komutunuzu da test ettim ve her ikisi de sekmeyi 2 boşlukla değiştirdi.) Öyleyse umarım Gnu sed'i yüklerseniz doğru kütüphaneyi de yükler.
— ctrl-alt-delor

Yanıtlar:


63

\tSed içindeki bir sekme karakterinin sözdizimi standart değil. Bu kaçış bir GNU sed uzantısıdır . Çevrimiçi kullanan bir çok örnek bulabilirsiniz çünkü birçok insan GNU sed kullanıyor (bu gömülü olmayan Linux'taki üst düzey uygulama). Fakat OS X sed , diğer * BSD sed gibi, \tsekmeyi desteklemiyor ve bunun yerine \tters eğik çizgi olarak görüyor t.

Gibi birçok çözüm vardır:

  • Bir hazır bilgi sekmesi karakteri kullanın.

    sed -i.bak 's/  /  /' file.txt
    
  • Sekme karakteri üretmek için trveya printfdüğmesini kullanın .

    sed -i.bak "s/$(printf '\t')/  /" file.txt
    sed -i.bak "s/$(echo a | tr 'a' '\t')/  /" file.txt
    
  • Ters eğik çizginin kaçmasına izin veren bash'in string sözdizimini kullanın .

    sed -i.bak $'s/\t/  /' file.txt
    
  • Perl, Python veya Ruby kullanın. Gönderdiğiniz Ruby pasajı işe yarıyor.


Bir ...sedkomut dosyasında bulunan sed komutları için ( -fseçenek aracılığıyla kullanılır ), değişmez sekme karakterleri benim için tek olasılık gibi görünüyor. Bunu vim ile düzenlerken set noexpandtabönemlidir.
— Tobias

Uyarı: İş arkadaşınızın arkanızdan geri gelmesini ve komut dosyanızı daha sonra kırmasını istiyorsanız, yalnızca bu "değişmez sekme karakteri" tekniğini kullanın. Bu trtekniği yalnızca , iş arkadaşınızın betiğinizi okuduklarında sizi yüzlerine bıçaklamalarını istiyorsanız kullanın.
— Bruno Bronosky

İkinci çift tırnak işareti ikinci kod bloğunda yanlış mı yerleştirildi? Şu anda kapanış tekli teklifin olduğu yere taşımak zorunda kaldım.
— Ellen Spertus

Bash string sözdiziminin bağlantısı için teşekkürler ... Hiçbir fikrim yoktu (ve bu en iyi seçenek, IMHO).
— levigroker

sed $'s/<regex>/\t/' file.txteklemek için çalışıyor, ancak $benim değiştirmeye regex'in bir kısmını dahil etmeye çalıştığımda senaryoyu kırıyor gibi görünüyor, yani sed $'s,\(ontology/[0-9]\+\),\t\txxx\1xxx\t\t,'`` ile eşleştiğim beklenen eşleşme değeri ile 'xxxxxx' veriyor. \1Bash'ın dize sözdizimini kullanırken buna eşdeğer bir var mı ? Düzenleme: xxx <U + 231C> xxx ortasında U + 231C unicode karakterinin olması gerekiyor.
— Josh

14

C gibi dizeleri kullanmanıza izin veren bir Bash'e özgü alıntı kullanın, böylece bir gerçek sekme karakteri bir kaçış dizisi yerine sed'e iletilir:

sed -i.bak -E $'s/\t/  /' file.txt

1
Ayrıca, diğerleri hakkında daha fazla bilgi edinmek istiyorsanız "ANSI-C" denir.
— WISBucky

2
Herhangi bir bourne kabuğu üzerinde çalışıyor gibi görünüyor, bash olmayan UNIX'lerde de çalışıyor. Yine de csh varyantlarında çalışmaz.
— jornane

1

Belirtildiği gibi, tüm seduygulamalar \tyatay bir sekme gösterimini desteklememektedir .

İkameinizi aşağıdakilerle kolayca yapabilirsiniz:

 perl -pi.old -e 's{\t+}{ }g' file.txt

Bu, orijinal dosyanızı "* .old" olarak koruyan bir yerinde değiştirme gerçekleştirir. Perl, klasik /ifadenin ifadeyi daha okunaklı kılması için alternatif sınırlayıcılara izin verir (yani "eğimli kürdan" sendromundan yoksun).

+Bir sekme özelliğine sahip bir veya daha fazla tekrar değiştirilmesi olduğunu söylüyor. gModifiye Her satırın sonunda boyunca küresel değiştirmeler sağlar.


1
sed -i $'s/\t/  /g' file.txt 

OS X'te benim için çalışıyor ve her zaman linux'da kullandığım komutla aynı.


Bunun, her satırdaki tüm sekmeleri değiştirdiğini, oysa OP'nin yalnızca ilkini değiştirmeyi düşündüğünü (kullandıkları komuttan değerlendirerek).
— Kusalananda

0

echoİçini de kullanabilirsiniz sed:

sed -i "s/$(echo '\t')//g"


echo '\t'Bunun sadece \tbazı mermilerin uygulanmasında çıktı olacağını unutmayın echo.
— Kusalananda

0

OS X'tekinden daha güçlü sed(destekleyici \tve daha fazla) istiyorsanız , GNU sed'i yükleyin .


Ruby ile çalışmadığı için, neden OS X'in sedsorun olduğu sonucuna varacağımdan emin değilim . Sorunun bu olduğuna inanmak için bir nedeniniz var mı? Sorunu çözeceğine inanmak için bir nedenim olsaydı GNU sed'i kurmaktan mutlu olurdum, ama sanırım bunu kesinlikle reddettim.
— iconoclast

Ruby ile, sadece bir ters eğik çizgi kullanmanız gerekir:ruby -pe '$_.gsub!(/\t/," ")' < file.txt
— vinc17

0

Gerekirse bashveya zshbir kabuk olarak sorun olmazsa , düşünebildiğim en kolay çözüm budur:

sed "s/$(echo -n -e "\t")/ /" file.txt

Bununla birlikte, echobayrakların ( -nve -e) POSIX'de tanımsız olduğunu, bu nedenle bir POSIX uygunluk kabuğu, bu bayrakların anlaşılmasını gerektirmez, ancak uyumluluk nedeniyle pek çok isteğin yapıldığını unutmayın .


-1

Hiç kimsenin çok basit bir çözüm önermediğine şaşırdım: sed -i.bak -E 's/\\\t/ /' file.txt İşin püf noktası olmalı.

Herşeyin yerine geçtiğinde normal ifadede \ t karakterini kullanmaya çalıştığınızı anlayabilmenizi sağlamak için kaçıştan (3 \ s) kaçmanız gerekir ...


Neden üç özel ters eğik çizgi?
— Michael Homer,

3
Eğer GNU'yu kullanırsam sed, \ kaçmak gerekmediğinden biri yeterlidir. Sorun, BSD'nin sedsekmeler için bu sözdizimini desteklememesidir.
— iconoclast

El Capitan'ımda çalışmıyor.
— Franklin Yu

-4

Bu benim için çalıştı.

sed -e 's / [\ t] / / g'


3
Bunun nedeni GNU kullanıyor olmanızdır sed. OP'nin kullandığı şey bu değil.
— Kusalananda
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.