Bir iş akışından (dosya) tüm ASCII olmayan karakterleri kaldırma


13

Ascii olmayan tüm karakterleri bir dosyadan nasıl kaldırabilirim? Bunu gerçekleştirmek için belirli bir komut var mı?

grep --colour='auto' -P -n'[^\x00-\x7]' /usr/local/...

Bunun iş akışı içindeki karakterleri bulduğuna inanıyorum, ancak söz konusu karakterlerin tüm örneklerini nasıl kaldırabilirim?



3
İlgili: Kontrol karakterleriyle ilgili problemlerden kaçınmak istiyorsanız (sessizce onlardan kurtulmak yerine), cat -vbunları ASCII temsilinde göstermek için kullanabilirsiniz. (örn. ^Giçin \007)
Matija Nalis

1
"Ascii olmayan karakterler" dediğinizde aksanlı karakterler de ekliyor musunuz?
Kaptan Adam

1
@MatijaNalis Temsil hakkında daha fazla bilgi: en.wikipedia.org/wiki/Caret_notation
wjandrea

1
Kullanım durumu nedir? Çoğu zaman, bir grup özel karakteri kaldırmaktan çok daha iyi çalışan belirli araçlar veya farklı yaklaşımlar vardır. ASCII'nin dikey sekmeler, zil ve NUL gibi birkaç "özel" karakter içerdiğini lütfen unutmayın - yazdırılabilir karakterler anlamına gelmediğinden emin misiniz ?
l0b0

Yanıtlar:


26

ASCII karakterleri, 0 ile 177 (sekizli) arasında değişen karakterlerdir .

Bir dosyada bu aralığın dışındaki karakterleri silmek için

LC_ALL=C tr -dc '\0-\177' <file >newfile

trKomut bir karakter çalışan bir araçtır ya da silme ya da bir tek karakteri aynı karakter silsileleri sıkıştırılması, diğer tek karakterler (çevirisi) ile ikame edilerek,.

Yukarıdaki komut filedeğiştirilen içeriği okuyacak ve yazacaktı newfile. -dSeçeneği tryarar silme karakterler (yerine onları transliterating arasında) yapar ve -cbunun verilen aralık (yerine içinin) dışında karakterleri dikkate yapar.

LC_ALL=Cher bayt değerinin geçerli bir karakter oluşturduğundan emin olur. Bu olmadan tr, yerel uygulamanın karakter kodlamasında geçerli karakterler oluşturmayan bayt dizileri bulduklarında bazı uygulamalar iptal olur.


Orijinal dosyayı değiştirilmiş olanla değiştirmek için şunu kullanın:

LC_ALL=C tr -dc '\0-\177' <file >newfile &&
mv newfile file

Bu trbaşarıyla tamamlandıktan sonra yeni dosyayı eski dosyanın adını yeniden adlandırır . Eğer trbaşarıyla tamamlanmaz orijinal dosyayı okuyamaz veya yeni bir dosyaya yazamadı çünkü ya, orijinal dosya değişmeden kalır.

Alternatif olarak, orijinal dosyanın meta verilerini (izinler vb.) Mümkün olduğunca korumak için şunu kullanın:

cp file tmpfile &&
LC_ALL=C tr -dc '\0-\177' <tmpfile >file &&
rm tmpfile


9

Tek ihtiyacınız olan bir normal ifade ise: [\x00-\x7F]birkaç yardımcı programa başvurabileceğiniz:

<file LC_ALL=C   sed   's/[^\o0-\o177]//g'      # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^\0-\177]/,"");print}'
<file            perl  -pe 's/[^[:ascii:]]//g;'
<file LC_ALL=C   tr    -dc '\0-\177'

Sed, awk ve perl'in Unix'te tanımlandığı gibi "metin dosyaları" beklediğini anlayın. Bu durumda hepsi iyi çalışıyor. Ancak özellikle awk, yeni bir satır ekler (kaynak dosyada var olsun ya da olmasın) (printf kullanarak girişteki TÜM yeni satırları kaldırır). Tr, herhangi bir dosya türüyle çalışacak şekilde tasarlanmıştır. Ancak, NUL ( \0) bir POSIX metin dosyasında geçerli bir karakter değildir ve bundan kaçınılmalıdır:

Satırlar NUL karakter içermiyor ...

Aslında, birçok kontrol karakteri bazı özel koşullar altında başka sorunlar yaratacaktır.
Yani, muhtemelen ihtiyacın var[\x07-\x0d\x20-\x7e]

<file LC_ALL=C   sed   's/[^\o007-\o015\o040-\o176]//g'            # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^\0-\15\40-\176]/,"");print}'
<file            perl  -pe 's/[^\x{7}-\x{d}\x{20}-\x{7e}]//g;'
<file LC_ALL=C   tr    -dc '\7-\15\40-\176'

7-13 aralığı (ondalık olarak) \a\b\t\n\v\f\r(sırayla).
Benzer (muhtemelen daha taşınabilir) bir aralık [^[:space:][:print:]] (similar because it doesn't include\ a \ b` --bell ve backspace--) olarak yazılabilir .

<file LC_ALL=C   sed   's/[^[:space:][:print:]]//g'  # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^[:space:][:print:]]/,"");print}'
<file            perl   -pe 's/[^[:space:][:print:]]//g;'
<file LC_ALL=C   tr     -dc '[:space:][:print:]'

İlgili:
Herhangi bir ASCII karakteri
Perl çözümü
Posix Metin Dosyası


Girilecek girdinin tryalnızca metin dosyaları değil, herhangi bir dosya türü olabileceğini unutmayın . awkÖte yandan, bir metin dosyası alır.
Kusalananda

Bir dosyaya "sadece ascii karakterler" adını vermek için "metin dosyası" dışında başka bir şey bulmak benim için oldukça zor (evet, evet: layman terimleriyle). @Kusalananda (yine de awk hakkında not eklendi).
Isaac

Bunun gensub()bir gawk uzantısı olduğunu unutmayın . Sen istersin gsub(...); printve (diğer) taşınabilir olması altıgen dizileri (ve LC_ALL = C) yerine sekizli kullanın.
Stéphane Chazelas

@ StéphaneChazelas Sözdizimi GNU'yu özel kılan GNU sed sınırlaması nedir (POSIXLY_CORRECT problemini anlıyorum).
Isaac

[^\o0]POSIX'te ters eğik çizgi, o ve 0 dışındaki karakterlerle eşleşmektir sed(GNU sed hariç tüm uygulamalarda). Bu , GNU'nun bir sınırlaması değil sed, uyumlu olmayan bir uzantıdır, bu nedenle POSIXLY_CORRECT ortamda olduğunda devre dışı bırakılır).
Stéphane Chazelas
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.