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.