ヒアドキュメントの定義は次のとおりです: http://en.wikipedia.org/wiki/Here_document
ヒアドキュメントにタブを入力するにはどうすればよいですか?このような:
cat > prices.txt << EOF
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
更新:
この質問で扱われる問題:
ヒアドキュメントをスクリプトに埋め込んで、別のファイルをまったく使用せずに変数に割り当てることができます。
#!/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
私の場合、ctrl-Vに続けてctrl-Iと入力して、bashシェルにタブを挿入します。これは、シェルがタブをインターセプトすることを回避します。それ以外の場合は、「特別な」意味があります。 Ctrl-Vの後にタブを付けることもできます。
ヒアドキュメントにドル記号を埋め込む場合は、シェル変数の補間を無効にするか、エスケープするために各変数の前に円記号を付ける必要があります(つまり、\$
)。
あなたのサンプルテキストを使用して、私はprices.txtにこのコンテンツを作成しました:
coffee\t.50
tea\t.50
burger\t.00
なぜなら$1
および$5
が設定されていません。補間は、ターミネータを引用することでオフに切り替えることができます。次に例を示します。
cat > prices.txt <<"EOF"
他の人が言っているように、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コマンドラインに貼り付けることができる「リテラルタブ付きで貼り付け」オプションがあります。
これは 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"
正解はすでに出ていますが、もっと簡潔な答えにまとめようとしています。
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の場合は、各エコーの外部プロセス)。
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
同様の方法で、ヒアドキュメントを使用して、変数を値に展開する新しいスクリプトを書き出して実行すると、コードをトレースするのではなく、実行された内容の正確な記録が得られます。
ヒアドキュメントに貼り付けられたタブは、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つは、$(echo $ '...')イディオムを使用することです。
cat > prices.txt << EOF
$(echo $'coffee\t$1.50')
$(echo $'tea\t$1.50')
$(echo $'burger\t$5.00')
EOF
@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
Sedのようなツールを使用し、区切り文字(EOF)を引用すると、作業が簡単になります。
sed 's/\\t/\t/g' > prices.txt << 'EOF'
coffee\t$1.50
tea\t$1.50
burger\t$5.00
EOF
\\t
のようなパターンがある場合は、sed -e 's/\\t/\t/g' -e 's/\\\t/\\t/g'
のようなより複雑なsed呼び出しが必要になります。