簡単な質問があります。
bash(私は4.4.11を使用しています)が、分離されている/プレーン\r
で終わる行/テキストを表示しないのは正常ですか?
この動作を見て、私は少し驚きました:
$ a=$(printf "hello\ragain\rgeorge\r\n")
$ echo "$a"
george
しかし、「こんにちは」というテキストはまだ残っています。どういうわけか「隠されています」:
$ echo "$a" |od -w32 -t x1c
0000000 68 65 6c 6c 6f 0d 61 67 61 69 6e 0d 67 65 6f 72 67 65 0d 0a
h e l l o \r a g a i n \r g e o r g e \r \n
そして、bashで遊ぶだけでいいのですが...これは潜在的なセキュリティリスクですか?変数 "a"の内容が外部の世界からのものであり、helloだけでなく "bad commands"が含まれている場合はどうなりますか?
別のテスト、今回は少し安全ではありません:
$ a=$(printf "ls;\rGeorge\n")
$ echo "$a"
George
$ eval "$a"
0 awkprof.out event-tester.log helloworld.c oneshot.sh rightclick-tester.py tmp uinput-simple.py
<directory listing appears with an error message at the end for command George>
非表示のrm
ではなく、非表示のls
を想像してみてください。
Echo -eを使用する場合の同じ動作:
$ a=$(echo -e "ls;\rGeorge\r\n"); echo "$a"
George
何か間違ったことをするのは私ですか...?
君の echo "$a"
は「hello」を出力してから、行の先頭に戻ります(これは\r
は)、「もう一度」印刷し、再び戻り、「george」を印刷し、再び戻り、次の行に進みます(\n
)。すべて完全に正常ですが、 chepner が指摘するように、Bashとは何の関係もありません:\r
および\n
は、Bashではなく端末によって解釈されます(コマンドをod
にパイプすると、完全な出力が得られるのはこのためです)。
あなたはこれをよりよく見ることができます
$ a=$(printf "hellooooo\r again,\rgeorge\r\n")
$ echo "$a"
それは上書きされたテキストの終わりを残すので:
georgen,o
ただし、実際にeval
を使用して(ただしeval
を使用して)、コマンドを非表示にすることはできません。通常は推奨されません)。より危険なトリックは CSSを使用してコマンドをマスクする Webサイトからコピーして貼り付けることです。
Unixの世界では、 キャリッジリターン (プログラミング言語では一般に\r
としてエンコードされます)は目立たない制御文字です。行の終わりを示す改行( newline とも呼ばれます)を除く他の文字と同様に、テキスト行内に改行を入れることができます。
特に、bashスクリプトでは、キャリッジリターンは文字や数字のような通常のWord構成文字です。キャリッジリターンの特殊効果は、シェルからではなくターミナルから発生します。
復帰は 制御文字 です。 glyph を表示する代わりに、ターミナルに出力すると、ターミナルは特別な効果を発揮します。復帰の場合、特殊な効果として、カーソルが現在の行の先頭に移動します。したがって、途中に改行を含む行を印刷すると、前半部分の上に後半部分が上書きされるという効果があります。
他のいくつかの制御文字には特別な効果があります。バックスペース文字はカーソルを1ポジション左に移動します。ベル文字は、端末に音を鳴らしたり、ユーザーの注意を引き付けたりします。エスケープ文字は エスケープシーケンス で始まり、あらゆる種類の特殊効果を持つことができます。
信頼できない出力を表示する場合は、制御文字をスクラブまたはエスケープする必要があります。キャリッジリターンだけでなく、その他のいくつか、特にエスケープ文字もさまざまな悪影響を引き起こす可能性があります。このトピックの詳細については、 ファイルを「キャッティング」することは潜在的なセキュリティリスクになる可能性がありますか? および 端末でのエスケープシーケンス攻撃を回避する方法? を参照してください。
%q
形式でprintf
関数を使用すると、bash変数の改行を表示できます。
$ TESTVAR="$(printf ' Version: 1 \r Build: 20180712 \r Test: 1324')"
$ printf %q $TESTVAR
Version:1$'\r'Build:20180712$'\r'Test:1324
出典および参考文献: