web-dev-qa-db-ja.com

ヒアドキュメントのbashにタブを入力するにはどうすればよいですか?

ヒアドキュメントの定義は次のとおりです: http://en.wikipedia.org/wiki/Here_document

ヒアドキュメントにタブを入力するにはどうすればよいですか?このような:

cat > prices.txt << EOF
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF

更新:

この質問で扱われる問題:

  1. tab文字を展開する
  2. ドル記号を展開していない間
  3. 埋め込みスクリプトなどのファイルへのヒアドキュメント
24
D W

ヒアドキュメントをスクリプトに埋め込んで、別のファイルをまったく使用せずに変数に割り当てることができます。

#!/bin/bash
read -r -d '' var<<"EOF"
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF

次に、printfまたはecho -e\t文字をタブに展開します。あなたはそれをファイルに出力することができます:

printf "%s\n" "$var" > prices.txt

または、printf -vを使用して、変数の値をそれ自体に割り当てます。

printf -v var "%s\n" "$var"

これで、varまたはファイルprices.txtには、\tの代わりに実際のタブが含まれます。

ヒアドキュメントを変数に格納したりファイルに書き込んだりする代わりに、読み取り時に処理することができます。

while read -r item price
do
    printf "The price of %s is %s.\n" $item $price    # as a sentence
    printf "%s\t%s\n" $item $price                  # as a tab-delimited line
done <<- "EOF"
    coffee $1.50    # I'm using spaces between fields in this case
    tea $1.50
    burger $5.00
    EOF

この場合、ヒアドキュメント演算子に<<-を使用したことに注意してください。これにより、読みやすくするためにヒアドキュメントの行をインデントできます。インデント必須タブのみで構成されます(スペースは含まれません)。

TAB="$(printf '\t')"

cat > prices.txt << EOF
coffee${TAB}\$1.50
tea${TAB}\$1.50
burger${TAB}\$5.00
EOF
19
chuck

私の場合、ctrl-Vに続けてctrl-Iと入力して、bashシェルにタブを挿入します。これは、シェルがタブをインターセプトすることを回避します。それ以外の場合は、「特別な」意味があります。 Ctrl-Vの後にタブを付けることもできます。

ヒアドキュメントにドル記号を埋め込む場合は、シェル変数の補間を無効にするか、エスケープするために各変数の前に円記号を付ける必要があります(つまり、\$)。

あなたのサンプルテキストを使用して、私はprices.txtにこのコンテンツを作成しました:

coffee\t.50
tea\t.50
burger\t.00

なぜなら$1および$5が設定されていません。補間は、ターミネータを引用することでオフに切り替えることができます。次に例を示します。

cat > prices.txt <<"EOF"
8
martin clayton

他の人が言っているように、CTRL-Vを入力してからTabキーを押すと、入力時に1つのタブを挿入できます。

テキストを貼り付けたい場合や、タブがたくさんある長いヒアドキュメントを入力したい場合など、bashタブ補完を一時的に無効にすることもできます。

bind '\C-i:self-insert'     # disable tab-completion

# paste some text or type your here-doc
# note you don't use "\t" you just press tab

bind '\C-i:complete'        # reenable tab-completion

編集:Macを使用していて iTerm 2 を使用している場合、タブ付きのコードをbashコマンドラインに貼り付けることができる「リテラルタブ付きで貼り付け」オプションがあります。

5
par

これは Dennis Williamson'sanswer の短いバージョンです。ここからのインスピレーション: http://tldp.org/LDP/abs/html/here-docs.html

#!/bin/bash

var=$(echo -e "$(cat <<"EOF"
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
)")

echo "$var"
2
Daniel Patru

正解はすでに出ていますが、もっと簡潔な答えにまとめようとしています。

1.1。 ヒアドキュメントにリテラルのタブ文字を含めることを妨げるものは何もありません。

Bashプロンプトでリテラルタブを入力するには、それをエスケープする必要があります。エスケープ文字はctrl-Vです(これをオーバーライドするカスタムバインディングがない場合)。

$ echo -n 't<ctrl-v><tab>ab' | hexdump -C
00000000  74 09 61 62                                       |t.ab|
00000004

ほとんどのプログラマーのエディターでは、リテラルタブ文字を挿入するのは簡単です(ただし、一部のエディターもエスケープしたい場合があります。Emacsでは、ctrl-Q TABがリテラルタブを挿入します)。

読みやすくするために、リテラルのタブ文字の代わりに、ある種のエスケープを使用する方がよい場合があります。 Bashでは、$ '...'文字列構文がこれに便利です。

2.2。 変数の拡張を防ぐには、すべてのドル記号を引用するか、ヒアドキュメントのターミネーターを引用符で囲みます。

$ hexdump -C <<HERE
> t<ctrl-v><tab>\$ab
HERE
00000000  74 09 24 61 62 0a                                 |t.$ab.|
00000006

$ hexdump -C <<'HERE'
> t<ctrl-v><tab>$ab
HERE
00000000  74 09 24 61 62 0a                                 |t.$ab.|
00000006

このコンテキストでは、一重引用符を使用するか二重引用符を使用するかは関係ありません。

3.3。 このサブ質問を理解できるかどうかわかりません。ヒアドキュメントの目的は、それをスクリプトに埋め込むことです。前の例は、スクリプトまたはコマンドラインでヒアドキュメントをhexdumpに渡す方法を示しています。

同じヒアドキュメントを複数回使用したい場合、それを直接行う簡単な方法はありません。スクリプトは、ヒアドキュメントを一時ファイルに書き込み、その一時ファイルを複数のコマンドに渡してから、一時ファイルを消去することができます。 (スクリプトが中断された場合にも、trapを使用して一時ファイルを削除するように注意してください。)

ヒアドキュメントの内容を変数に入れて、それを補間することもできます。

# Note embedded newlines inside the single quotes,
# and the use of $'...\t...' to encode tabs
data=$'coffee\t$1.50
tea\t$1.50
burger\t$5.00'

# Run Word Count on the data using a here document
wc <<HERE
$data
HERE

# Count number of tab characters using another here document with the same data
grep -c $'\t' <<HERE
$data
HERE

同等にecho -E "$data" | wc; echo -E "$data" | grep -c $'\t'を使用することもできますが、echoの使用はあまりエレガントではなく、移植性が低い可能性があります(ただし、ターゲットがbashの場合、すべてのエコーは同じである必要があります。ターゲットが一般にBourne Shellの場合は、各エコーの外部プロセス)。

2
tripleee

Re:サブ質問#3、私はこの質問を次のように読みました:

「[...]コメントしたヒアドキュメントを後で参照できるようにスクリプトと同じファイルに保存したい場合はどうすればよいですか?」

エグゼキュータにも書き込み権限があると仮定して、スクリプト名をヒアドキュメントの出力として使用し、置き換えるのではなく追加します。シェルコメントは、ヒアドキュメントブロックでは解釈されません。

_thisline=${LINENO}
cat <<EOF >>$0
#====== $(date) =========
#On this run, these variable values were used as of line ${_thisline}: A=${A}, B=${B}, B=${C}

EOF

同様の方法で、ヒアドキュメントを使用して、変数を値に展開する新しいスクリプトを書き出して実行すると、コードをトレースするのではなく、実行された内容の正確な記録が得られます。

1
chrissm

ヒアドキュメントに貼り付けられたタブは、bashがオートコンプリートシーケンス/リクエストの開始を示す特殊文字として解釈しているため、表示されなくなります。

現在のシェルにヒアドキュメントをすばやく貼り付けたい場合は、現在のシェルの存続期間中、オートコンプリートを無効にすることでこれを行うことができます。

タブを含むヒアドキュメントを貼り付けると、通常のオートコンプリートで何が起こるかを次に示します。

$ cat <<EOF
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
EOF
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE
TABAFTERTABBEFORE

次のコマンドを実行します。

bind "set disable-completion on"

もう一度貼り付けると、タブが保持されます。

$ cat <<EOF
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> TABAFTER      TABBEFORE
> EOF
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
TABAFTER    TABBEFORE
1
javabrett

元の問題に対する簡単で直接的な解決策の1つは、$(echo $ '...')イディオムを使用することです。

cat > prices.txt << EOF
$(echo $'coffee\t$1.50')
$(echo $'tea\t$1.50')
$(echo $'burger\t$5.00')
EOF
0
peak

@EOFを使用すると、タブが保持されます。

cat >> /etc/logrotate.d/nginx <<@EOF
/var/log/nginx/*log { 
    daily
    rotate 10
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
        /bin/kill -USR1 $(cat /var/run/nginx.pid 2>/dev/null) 2>/dev/null || :
    endscript
}
@EOF
0
LinuxGuru

Sedのようなツールを使用し、区切り文字(EOF)を引用すると、作業が簡単になります。

sed 's/\\t/\t/g' > prices.txt << 'EOF'
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
  • EOFは、パラメーター(ドル記号)の展開を防ぎます。
  • sedは「\ t」をタブ文字に変換します。
  • ヒアドキュメントに\\tのようなパターンがある場合は、sed -e 's/\\t/\t/g' -e 's/\\\t/\\t/g'のようなより複雑なsed呼び出しが必要になります。
0
Walker Hale IV