TABで区切られた文字列をbashで印刷する方法は?


9

タブで区切られた2つの文字列を印刷しようとしています。私が試してみました:

echo -e 'foo\tbar'
printf '%s\t%s\n' foo bar

それらの両方が印刷します:

foo     bar

2つの間の空白は実際には5つのスペースです(パテでマウスを使用して出力を選択する場合)。

コマンドを入力するときにCTRL + Vを使用してTabキーを押しても同じ結果が得られました。

タブをタブとして強制的に印刷する正しい方法は何ですか?出力を選択して、タブを使用して別の場所にコピーできますか?

そして2番目の質問:bashがタブをスペースに展開するのはなぜですか?

更新:どうやら、これはパテの問題です:https : //superuser.com/questions/656838/how-to-make-putty-display-tabs-within-a-file-instead-of-changing-them-to -スペース



なぜそれを逃さないのですか? printf '%s\\t%s\n' foo bar
Valentin Bajrami 2018

@steeldriverありがとう、私が必要としているものと非常によく似ていますが、最終的には解決策はありません...
Asu

1
@Valentin出力foo\tbar...
wjandrea 2018

1
あなたがあなたのターミナルに問題があることをあなたがすでに知っているという事実にもかかわらず:Bashはそれ自体$'\t'がタブレータとして解釈します。したがって、たとえば割り当てとして次のように常に文字列を連結することができます。v='This is'$'\t''a test'そして、それを文字どおりに出力します。例:printf '%s' "$v"
rexkogitans

回答:


9

ilkkachuが言ったように、これはbashの問題ではなく、出力時にタブをスペースに変換するターミナルエミュレーターの問題です。

異なる端末をチェックすると、putty、xterm、konsoleはタブをスペースに変換しますが、urxvtとgnome-terminalは変換しません。したがって、別の解決策は、端末を切り替えることです。


3
これは、を実行しstty tab3た後、ttyドライバーでも実行できます。
ステファンChazelas

14

2つの間の空白は実際には5つのスペースです。

いいえ、ちがいます。echoまたはの出力にはありませんprintf

$ echo -e 'foo\tbar' | od -c
0000000   f   o   o  \t   b   a   r  \n
0000010

タブをタブとして強制的に印刷する正しい方法は何ですか?出力を選択して、タブを使用して別の場所にコピーできますか?

これは別の問題です。これは、シェルではなく、出力時にタブをスペースに変換するターミナルエミュレータに関するものです。多くの人がそうしているわけではありません。

タブ付きの出力をファイルにリダイレクトしてそこからコピーしたりunexpand、出力でスペースをタブに変換したりする方が簡単な場合があります。(ただし、最初は空白であるタブを知ることはできません。可能な場合はすべての空白がタブに変換されます。)もちろんこれは、出力をどのように処理する必要があるかによって異なります。


つまり、出力を選択しようとすると、5つのスペースとして扱われます。コマンド出力の内容を確認するための「od -c」をありがとう。
Asu

1
@あす私は彼がそれを理解していると思います。彼の解決策は、ターミナルエミュレータがウィンドウでタブを選択したときにタブとしてタブを残すことが保証されていないため、他の方法で出力を取得することです。ただし、チェックしたところ、putty、xterm、konsoleはタブをスペースに変換しますが、urxvtとgnome-terminalは変換しません。したがって、別の解決策は、端末を切り替えることです。
JoL、

@JoLはい、それは私がちょっと前に来た結論です、そして誰かがそれをそのように投稿したいと思ったらそれは受け入れられた答えだと思います...
Asu

1
@Asu、そうです、問題を手動で回避することを考えました。それをしなければならないのは面倒ですが、タブのコピーをサポートする端末エミュレータがあることに気づかなかったと私は認めます。もちろん、そうするように変更すれば、はるかに優れたソリューションになるでしょう
ilkkachu 2018

4

ではprintf '%s\t%s\n' foo barprintf出力を行いますfoo<TAB>bar<LF>

fobaおよびrシングル幅のグラフィカルな文字です。

これらの文字を受信すると、端末は対応するグリフを表示し、画面の右端(元のテレタイプライターの紙)に既に達していない限り、カーソルを1列右に移動します。画面の左端に戻る(折り返す)か、端末とその構成方法に応じて文字を破棄します。

<Tab><LF>2つの制御文字です。<LF>(別名改行)は、Unixテキストの行区切り文字ですが、ターミナルの場合は、改行するだけです(カーソルを1つ下に移動します)。そのため、カーネルのターミナルドライバーは実際にそれを<CR>(画面の左端に戻る)、<LF>(カーソルを下に)に変換します(stty onlcr通常はデフォルトでオンです)。

<Tab> ギャップを空白で埋めることなく、カーソルを次のタブストップ(ほとんどの端末ではデフォルトで8ポジション離れていますが、どこにでも設定できるように構成できます)に移動するように端末に指示します。

したがって、カーソルが空の行の先頭にあるときに、これらの文字が8列ごとにタブストップでターミナルに送信されると、次のようになります。

foo     bar

画面のその行に印刷されます。を含む行の3番目の位置にカーソルがあるときに送信された場合は、次のようになりますxxxxyyyyzzzz

xxfooyyybarz

集計をサポートしていない端末では、これらのタブを一連のスペースに変換するように端末ドライバを構成できます。(stty tab3)。

SPC文字は、元のテレタイプライターではカーソルを右に移動し、バックスペース(\b)を使用すると左に移動します。現在の端末では、SPCが右に移動し、消去されます(期待どおりにスペース文字が書き込まれます)。したがって、ペンダントは\bASCIIよりも新しいものでなければなりませんでした。最も近代的な端末では、それは実際の文字列です:<Esc>[C

n文字を左、右、上、下、または画面上の任意の位置に移動するためのエスケープシーケンスがあります。画面の行や領域の一部を消去(空白で埋める)するためのエスケープシーケンスは他にもあります。

これらの配列は、典型的には、のような視覚的なアプリケーションで使用されvilynxmuttdialogテキストが画面上の任意の位置に書き込まれます。

現在、すべてのX11端末エミュレータと、GNUのような他のいくつかの非X11エミュレータscreenでは、画面の領域をコピーして貼り付けることができます。viエディターに表示されている部分を選択する場合、その出力の生成に使用されたすべてのエスケープシーケンスをコピーする必要はありません。そこに表示されているテキストを選択します。

たとえば、次を実行した場合:

printf 'abC\rAC\bB\t\e[C\b\bD\n'

これは、を入力abCし、最初に戻り、と置き換え、と置き換え、次のタブ位置に移動し、次に右に1列、次に左に2列移動しabACCと入力するエディターセッションをシミュレートしBますD

分かりますか:

ABC    D

つまりABC、4列のギャップとDです。

あなたがマウスでそれを選択した場合xtermputty、それらを選択して保存するABC、4つの空白文字をしてD、ではありませんabC<CR>AC<BS>B<Tab><Esc>[C<BS><BS>D

printf最終的に選択されるのは、送信されたものですが、ターミナルドライバーとターミナルエミュレーターの両方によって後処理されます。

他の種類の変換については、によって(前に合成された形式)に変更された<U+0065><U+0301>eその後に結合する急性アクセントが続く)を参照してください。<U+00E9>éxterm

またはecho abc、それはABC、ターミナルドライバーによって変換されてから、ターミナルに送信されstty olcucます。

さて、は<Tab><LF>テキストファイル(<CR>MSDOSテキストファイル、および<FF>改ページ用)に実際に見つかるいくつかの制御文字の1つです。

そのため、一部のターミナルエミュレータは、可能な場合はコピーアンドペーストバッファにコピーしてそれらを保持することを選択します(通常、そうではあり<CR>ませ<LF>ん)。

たとえば、のようなVTEベースの端末gnome-terminalprintf 'a\tb\n'は、空の行での出力を選択すると、gnome-terminal実際a\tbにはa、7スペースとの代わりにX11選択に格納されることがわかりますb

しかし、の出力のprintf 'a\t\bb\n'場合はa、6つのスペースとが格納され、のb場合printf 'a\r\tb\n'a、7つのスペースとが格納されますb

端末が実際の入力をコピーしようとするケースは他にもあります。たとえば、実行後に2行を選択するprintf 'a \nb\n'と、見えない後続スペースが保持されます。または、2つの行を選択したときに、2つの行が右マージンでの折り返しの結果である場合、LF文字が含まれません。

ここで、の出力をprintfCLIPBOARD X11selectに保存する場合は、次のように直接実行することをお勧めします。

printf 'foo\tbar\n' | xclip -sel c

あなたがいることを貼り付けることを注意xtermまたは他のほとんどの端末、xterm実際にその置き換え\n\rそれが文字だからxterm、あなたが押したときに送信Enter(と端末ドライバがバックにそれを翻訳することができます\n)。


これは非常に洞察に富んでいます、ありがとう。私はxclipソリューションを試しましたが、うまくいきます。しかし、それは私が心に描いたとおりには機能せず、X11を必要とします。これはいつか重宝するでしょう、ありがとう!
Asu

@Asuは、X11のような端末エミュレータでのコピー&ペーストの選択取り扱うものですxtermputtyUnix上を。他の端末エミュレータは、GNU画面のコマンドreadbufregisterコマンドのように、独自のコピーアンドペーストメカニズムと任意のコンテンツをそこに格納する方法を備えている場合があります。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.