bashスクリプトのタブ文字のエコー


313

bashスクリプトを使用して1つ以上のタブ文字をエコーするにはどうすればよいですか?このコードを実行すると

res='       'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

私はこれを手に入れます

res=[ x] # that is [<space>x]

回答:


529
echo -e ' \t '

「スペースタブスペース改行」をエコーし​​ます(-e「バックスラッシュエスケープの解釈を有効にする」を意味します):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|

ヨハネスに感謝します。あなたは私がこの解決策を見つけるのを助けました:res = '\ t \ t'x; echo -e '[' $ res ']'
kalyanji

2
あなたはたまたま知っていますか、なぜecho -eMakefileで機能しないのですか?
dma_k 2010年

23
これecho -eは、がPOSIXではなく、通常はプログラムで使用されないmake呼び出し/bin/shがインタラクティブに使用-eされ、通常は実装されていないためです。移植性のためprintf '\t'に、代わりに使用してください。
Jo So

Darwin(macOS)ではmanechoコマンドのページにオプションが記載されていません-e。ただし、このオプションは受け入れられます。
ePi272314

75

printfではなくを使用してくださいecho

echoコマンドには複数の異なるバージョンがあります。あります/bin/echo(またはシステムに応じて、GNUのCoreutilsバージョンであってもなくてもよい)、およびechoコマンドはほとんどのシェルに組み込まれています。バージョンによって、制御文字のエスケープを指定または無効にする方法が異なります(または方法がありません)。

printf一方、変動ははるかに少なくなります。これは通常/bin/printf、コマンドとして存在することができ、一部のシェルに組み込まれています(bashとzshにはありますが、tcshとkshにはありません)echo。また、コマンドラインオプションを覚えておく必要はありません(いくつかの例外があります。GNUCoreutils printfは--versionおよびを受け入れ--help、組み込みのbash printfは-v var出力を変数に格納することを受け入れます)。

あなたの例のために:

res='           'x # res = "\t\tx"
printf '%s\n' "[$res]"

そして今、私がechoあなたが尋ねている例と同じように機能することを認める時が来ました。引数を二重引用符で囲むだけです:

echo "[$res]"

kmkaplanが書いたように(2年半前、私は気づきました!)。元のコマンドの問題:

res='           'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

とは異なりechoます。それは、シェルがechoこれまで見たことのないスペースでタブを置き換えたことです。

echoのような単純な出力には問題ありませんが、もっと複雑なことをしたいときはいつでもecho hello world使用する必要がありますprintf。あなたはでき得るecho仕事に、しかし、結果のコードは、あなたが異なるとそれを実行すると失敗する可能性がありecho、実装または別のシェル。


1
私はこれが好きで、printfとすべてのフォーマット指定子の知識を使用できます。
アルン

@JezenThomas:要求されたのとは別の方法で質問に回答するため、これ以上の賛成はありません。質問は特にエコーに言及しており、エコーは動詞ではなくコマンドです。
Paulo Neves、2017年

@PauloNeves:「bashスクリプトを使用して1つ以上のタブ文字をエコーするにはどうすればよいですか?」という質問の動詞として使用されていると思います。
キーストンプソン、

34

文字列を二重引用符で囲みます。

echo "[$res]"

1
ここでも同じです-これは私が最初に試したものです -eはうまくいきましたが
froderik

2
@kmkaplanはzshで動作します-bashで動作しません
Kal

34

あなたも試すことができます:

echo Hello$'\t'world.

4
より一般的なソリューションの場合は+1。私は何年もbashを使用してきましたが、今これを学びました!
Aryeh Leib Taurog

エコーなしで使用できるため、これは受け入れられた回答よりもはるかに一般的です。
jwan


16

bashのmanページから:

$ 'string'形式の単語は特別に扱われます。単語は文字列に展開され、バックスラッシュでエスケープされた文字はANSI C規格の指定に従って置き換えられます。

だからあなたはこれを行うことができます:

echo $'hello\tworld'

なぜこれはcliでは機能するがbashスクリプトでは機能しないのですか?
Freek、

13

、そのままキーストロークを使用し^VCTRL+VC-v何でも)。

あなたが入力すると^V(またはほとんどのUnixのエディタで)端子に、以下の文字が取られ逐語的に。これを使用して、エコーする文字列内にリテラルタブ文字を入力できます。

次のようなもの:

echo "^V<tab>"     # CTRL+V, TAB

Bash docsqv、 "quoted-insert")

quoted-insert(Cq、Cv)入力した次の文字をそのまま行に追加します。これは、Cqなどのキーシーケンスを挿入する方法です。

補足:これに従って ALT+TAB 、同じことを行う必要がありますが、そのシーケンスはすべてウィンドウ切り替えにバインドしているため、使用できません。

tab-insert(M-TAB)タブ文字を挿入します。

-

注:この戦略は、あらゆる種類の変わった文字で使用できます。キャリッジリターンのように:

echo "^V^M"        # CTRL+V, CTRL+M

これは、キャリッジリターンがASCII 13であり、Mがアルファベットの13番目の文字であるため、と入力^Mすると、13番目のASCII文字が返されます。ls^M空のプロンプトで、を使用して動作を確認できます。これにより、改行が挿入され、Enterキーを押すのと同じようにプロンプ​​トが機能します。これらの文字が正常に解釈されると、逐語的にリテラル文字を取得します。


1
これにもっと賛成票を差し上げたいと思います。この場合、引数に-eを使用したくありませんでした。これはうまく機能します。ありがとう!
アーロンR.

「...ほとんどのUnixエディタ」?viとemacsの両方でこれを入力しようとしましたが、どちらでも望ましい結果が得られませんでした。
GreenMatt

かっこいい!文字grepを含む行をキャッチするために使用するときに私の日を節約しましたtab
ジョエル

11

エコーを使用して変数の値を出力することは、一般的なBashの落とし穴です。参照リンク:

http://mywiki.wooledge.org/BashPitfalls#echo_.24foo


かっこいい、私は「BashPitfalls」、素晴らしい素材が好きで、毎日の仕事の多くの痛みを和らげます!
Jerry Tian、

これは真実であるため、+ 1。ただし、kalyanji文字列は「[」で始まり、「\」を含まないことに注意してください。
kmkaplan 2012年

2

echo "a\tb"スクリプトで使用する場合は、次のようにスクリプトを実行します。

# sh -e myscript.sh

または、myscript.shに実行権限を付与して、スクリプトを実行することもできます。

# chmod +x myscript.sh
# ./myscript.sh

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.