「-c」オプションと2拡張子を設定した「tr」が最後に不要な文字を追加するのはなぜですか?

「-c」オプションと2拡張子を設定した「tr」が最後に不要な文字を追加するのはなぜですか?

tr文字列の「違法」文字がすべて「許可」文字セットの外側にある「違法」文字を置き換える文字(つまりこれは許可される文字セットに追加されます。ただし、この-cオプションを明示的な反復*指定子または「セット2」の暗黙的な拡張とともに使用すると、tr追加出力用の代替文字のインスタンスです。

また現れる

  • 「許可される」文字をa-n文字通りに指定しますabcdefghijklmn
  • 代替文字をにしておきますz
  • 入力文字列をhellまたはのままにしますhello。予想される出力文字列はthenhellとですhellz

デモ

  1. 無効な文字が存在します。暗黙のセット 2 拡張子です。

    $ echo "hello" | tr -c 'abcdefghijklmn' 'z'
    hellzz
    

    予想される出力はですhellz

  2. 文字のみが許可され、暗黙のセット2拡張子です。

    $ echo "hell" | tr -c 'abcdefghijklmn' 'z'
    hellz
    

    予想される出力はですhell

  3. 無効な文字が存在します。 2つの拡張子を明示的に設定しました。

    $ echo "hello" | tr -c 'abcdefghijklmn' '[z*]'
    hellzz
    

    予想される出力はですhellz

  4. 文字のみが許可され、明示的に2つの拡張子を設定します。

    $ echo "hell" | tr -c 'abcdefghijklmn' '[z*]'
    hellz
    

    予想される出力はですhell

  5. echo-pipeの代わりにhere-stringを使用しても同じことが起こります(実際、here-stringは私がこの効果を最初に見つけたときに使用した設定でした)。

    $ tr -c 'abcdefghijkl' '[z*]' <<< "hello"
    hellzz
    

trなぜここに1つを追加するのですかz

これはLinuxでbash、UTF-8ロケールを使用し、trGNU coreutils 8.25および8.30を使用します。

ベストアンサー1

echoこれは、印刷するように指示した内容の末尾に改行文字が追加されるためです。ここで文字列を使用しても同様です。

したがって、echo "hello"実際に印刷されますhello\n

$ echo hello | od -c
0000000   h   e   l   l   o  \n
0000006

これがまさにあなたがこれを見る理由です:

$ echo "hell" | tr -c 'abcdefghijklmn' 'z'
hellz$

そこには末尾の改行はなく、$私のプロンプトが最後に表示されます。これは、最後に印刷された内容が置き換えられるためzです。\nhello\nzprintf

$ printf "hello" | tr -c 'abcdefghijklmn' 'z'
hellz$

printf %s "$string"任意の文字列の場合はno printf "$string"

またはecho、それをサポートしているものを使用している場合は、以下を使用してくださいecho -n

$ echo -n "hello" | tr -c 'abcdefghijklmn' 'z'
hellz$

echoまたは、標準のUNIX(およびオプションがすべて有効な場合は組み込みのような)がある場合は、echo出力を停止する原因を使用してください。bashposixxpg_echo\cecho

$ echo 'hello\c' | tr -c 'abcdefghijklmn' 'z'
hellz$

ただし、出力がまだ正しいテキストになるように、入力に対応する行区切り文字を保持しようとする可能性が高くなります。

printf '%s\n' "$string" | tr -c 'abcdefghijklmn\n' '[z*]'

(代わりに標準のPOSIX構文が使用され、改行をより明確に追加し、文字で始まる、または文字を含むprintf文字列に関連する問題を回避します。)echo-\

trまた、実装によっては個別に文字としてデコードできないバイトが残ることがありますが(変更されませんz)、他の場合(たとえば、GNU)では、tr文字ごとに単一の文字(およびロケールセット)バイトを持つテキストに対してのみ機能します。

sed別のアプローチは、少なくともGNU実装ではこれに関してよりうまく機能する方法を使用することです。

sed 's/[^abcdefghijklmnz]/z/g'

sedその仕事をするコンテンツ改行は自動的に維持されます。

おすすめ記事