ワークフロー(ファイル)から非ASCII文字をすべて削除する


12

1つのファイルからすべての非ASCII文字を削除するにはどうすればよいですか?これを実行する特定のコマンドはありますか?

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

これでワークフロー内のキャラクターが見つかると思いますが、問題のキャラクターのインスタンスをすべて削除するにはどうすればよいですか?



2
関連:制御文字の問題を(静かに除去するのではなく)単に回避したい場合は、単にcat -vそれらをASCII表現で表示するために使用できます。(例えば^G\007
マティヤNalis

1
「非ASCII文字」と言うとき、アクセント記号付きの文字も含まれますか?
キャプテンマン

1
@MatijaNalis表現に関する詳細:en.wikipedia.org/wiki/Caret_notation
wjandrea

1
ユースケースは何ですか?非常に多くの場合、特定のツールやさまざまなアプローチがあり、それらは特別な文字を単に削除するよりもはるかに効果的です。ASCIIには、垂直タブ、ベル、NULなどのいくつかの「特殊な」文字が含まれていることに注意してください。印刷可能な文字を意味しないのですか?
l0b0

回答:


25

ASCII文字は、0〜177(8進数)の範囲の文字です。

ファイル内のこの範囲外の文字を削除するには、次を使用します

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

このtrコマンドは、単一の文字動作するユーティリティであり、他の単一の文字で置換(音訳)、削除、または同じ文字の実行を単一の文字に圧縮します。

上記のコマンドはfile、変更されたコンテンツを読み書きしnewfileます。-dオプションは、tr(代わりにそれらを翻字の)ユーティリティ、削除文字を作り、-cそれが(代わりに内部の)一定の間隔外の文字を検討します。

LC_ALL=Cすべてのバイト値が有効な文字を構成していることを確認します。それtrがないと、ロケールの文字エンコーディングで有効な文字を形成しないバイトシーケンスが見つかった場合、一部の実装は中止されます。


元のファイルを変更したファイルで置き換えるには、次を使用します

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

これにより、tr正常に完了した後、新しいファイルの名前が古いファイルの名前に変更されます。tr元のファイルを読み取れなかったか、新しいファイルに書き込めなかったために正常に完了しなかった場合、元のファイルは変更されないままになります。

または、元のファイルのメタデータ(許可など)をできるだけ保存するには、

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


9

必要なのが正規表現[\x00-\x7F]だけの場合:いくつかのユーティリティに適用できます:

<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、perlはUnixで定義されている「テキストファイル」を想定していることを理解してください。この場合、すべてうまくいきます。ただし、具体的には、awkは末尾の新しい行を追加します(ソースファイルに存在するかどうかに関係なく)(printfを使用すると、入力のすべての改行が削除されます)。trは、あらゆる種類のファイルで動作するように設計されています。ただし、NUL(\0)はPOSIXテキストファイルでは有効な文字ではないため、避ける必要があります。

行にはNUL文字が含まれていません...

実際、多くの制御文字は、特定の条件下で他の問題を生成します。
だから、おそらくあなたが必要です[\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(10進数)は\a\b\t\n\v\f\r(順番)です。
同様の(おそらくより移植性の高い)範囲は[^[:space:][:print:]] (similar because it doesn't include\ a \ b` --bellとbackspace--)と書くことができます。

<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:]'

関連:
ASCII文字の正規表現
Perlソリューション
Posixテキストファイル


への入力trは、テキストファイルだけでなく、任意のタイプのファイルにできることに注意してください。awk一方、テキストファイルを受け取ります。
クサラナナンダ

ファイルを「テキストファイル」以外の「アスキー文字のみ」と呼ぶ他の何かを見つけることは非常に困難です(はい、はい:素人の用語で)。@Kusalananda(とにかくawkが追加されていることに注意)。
アイザック

これgensub()はgawk拡張機能であることに注意してください。あなたはgsub(...); print、16進シーケンス(およびLC_ALL = C)の代わりに8進を使用して(より)移植可能にする必要があります。
ステファンシャゼラス

@StéphaneChazelas構文をGNU固有にするGNU sedの制限は何ですか(POSIXLY_CORRECT問題を理解しています)。
アイザック

[^\o0]バックスラッシュ、POSIXのoおよび0 sed(GNU sedを除くすべての実装)以外の文字に一致します。これはGNUの制限ではsedなく、非準拠の拡張機能です。そのため、POSIXLY_CORRECTが環境にある場合は無効になっています。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.