bash継続行をどのように使用しますか?
私はあなたがこれを行うことができることを理解しています:
echo "continuation \
lines"
>continuation lines
ただし、インデントされたコードがある場合、うまく機能しません。
echo "continuation \
lines"
>continuation lines
bash継続行をどのように使用しますか?
私はあなたがこれを行うことができることを理解しています:
echo "continuation \
lines"
>continuation lines
ただし、インデントされたコードがある場合、うまく機能しません。
echo "continuation \
lines"
>continuation lines
回答:
これはあなたが望むかもしれないことです
$ echo "continuation"\
> "lines"
continuation lines
これがエコーする2つの引数を作成し、1つだけが必要な場合は、文字列の連結を見てみましょう。bashでは、2つの文字列を互いに隣接して配置します。
$ echo "continuation""lines"
continuationlines
したがって、インデントのない継続行は、文字列を分割する 1つの方法です。
$ echo "continuation"\
> "lines"
continuationlines
しかし、インデントが使用されている場合:
$ echo "continuation"\
> "lines"
continuation lines
これはもはや連結ではないため、2つの引数が得られます。
行を横切る単一の文字列が必要で、インデントはしているがすべてのスペースは取得していない場合は、継続行を破棄して変数を使用する方法があります。
$ a="continuation"
$ b="lines"
$ echo $a$b
continuationlines
これにより、追加の変数を犠牲にして、コードをきれいにインデントすることができます。変数をローカルにすると、悪くないはずです。
s="string no. 1" s+="string no. 2" s+=" string no. 3" echo "$s"
ここで、<<-HERE
ターミネータ付きのドキュメントは、インデントされた複数行のテキスト文字列に適しています。ヒアドキュメントから先頭のタブを削除します。(ただし、ラインターミネータは残ります)。
cat <<-____HERE
continuation
lines
____HERE
http://ss64.com/bash/syntax-here.htmlも参照してください
すべてではなく一部の先頭の空白を保持する必要がある場合は、次のようなものを使用できます
sed 's/^ //' <<____HERE
This has four leading spaces.
Two of them will be removed by sed.
____HERE
または多分tr
改行を取り除くために使用します:
tr -d '\012' <<-____
continuation
lines
____
(2行目には前にタブとスペースがあります。タブは、ヒアドキュメントのターミネーターの前にダッシュ演算子によって削除されますが、スペースは保持されます。)
長い複雑な文字列を多くの行でラップするために、私は好きprintf
です:
printf '%s' \
"This will all be printed on a " \
"single line (because the format string " \
"doesn't specify any newline)"
また、あなたがそのようなのように、ここで文書を使用しますが、ホスト言語の構文はさせません別の言語でのシェルスクリプトの埋め込み自明でない作品にしたい場面でうまく動作しますMakefile
かDockerfile
。
printf '%s\n' >./myscript \
'#!/bin/sh` \
"echo \"G'day, World\"" \
'date +%F\ %T' && \
chmod a+x ./myscript && \
./myscript
printf
例も今すぐ参照してください。)
Bashの連結機能を利用する特定のシナリオでは、適切な場合があります。
temp='this string is very long '
temp+='so I will separate it onto multiple lines'
echo $temp
this string is very long so I will separate it onto multiple lines
名前= [値] ...
...割り当てステートメントがシェル変数または配列インデックスに値を割り当てるコンテキストでは、+ =演算子を使用して、変数の以前の値に追加または追加できます。+ =が整数属性が設定されている変数に適用されると、valueは算術式として評価され、変数の現在の値に追加されます。これも評価されます。+ =が複合代入を使用して配列変数に適用される場合(以下の配列を参照)、変数の値は設定解除されず(=を使用する場合のように)、新しい値が配列の最大インデックスよりも大きい値で始まる配列に追加されます(インデックス付き配列の場合)、または連想配列のキーと値のペアとして追加されます。 文字列値の変数に適用されると、値は展開され、変数の値に追加されます。
コマンド引数の一部として長いメッセージを送信しなければならず、行の長さの制限を遵守しなければならない状況に遭遇しました。コマンドは次のようになります。
somecommand --message="I am a long message" args
私がこれを解決した方法は、メッセージをヒアドキュメント(@tripleeeのような)として移動することです。しかし、ヒアドキュメントは標準入力になるので、それを読み戻す必要があるので、以下のアプローチを採用しました:
message=$(
tr "\n" " " <<- END
This is a
long message
END
)
somecommand --message="$message" args
これには、$message
余分な空白や改行なしで文字列定数とまったく同じように使用できるという利点があります。
上記の実際のメッセージ行には、tab
それぞれ文字がプレフィックスとして付けられていることに注意してください。これは、(を使用しているため)ドキュメント自体によって削除されます<<-
。末尾にはまだ改行がありdd
、スペースで置き換えられます。
また、改行を削除しないと、"$message"
が展開されたときにそのまま表示されます。場合によっては、の二重引用符を削除することで回避できること$message
がありますが、メッセージは単一の引数ではなくなります。
構文の巧妙な使用により、行の継続も実現できます。
の場合echo
:
# echo '-n' flag prevents trailing <CR>
echo -n "This is my one-line statement" ;
echo -n " that I would like to make."
This is my one-line statement that I would like to make.
varsの場合:
outp="This is my one-line statement" ;
outp+=" that I would like to make." ;
echo -n "${outp}"
This is my one-line statement that I would like to make.
変数の場合の別のアプローチ:
outp="This is my one-line statement" ;
outp="${outp} that I would like to make." ;
echo -n "${outp}"
This is my one-line statement that I would like to make.
出来上がり!
次のように、インデント内で必要に応じて、単に(バックスラッシュを使用せずに)改行で区切ることができ、新しい行を削除します。
例:
echo "continuation
of
lines" | tr '\n' ' '
または、変数定義の場合、改行は自動的にスペースに変換されます。そのため、該当する場合にのみ、余分なスペースを取り除いてください。
x="continuation
of multiple
lines"
y="red|blue|
green|yellow"
echo $x # This will do as the converted space actually is meaningful
echo $y | tr -d ' ' # Stripping of space may be preferable in this case
これは正確にはユーザーが求めたものではありませんが、複数行にまたがる長い文字列を作成する別の方法は、次のように徐々に構築することです。
$ greeting="Hello"
$ greeting="$greeting, World"
$ echo $greeting
Hello, World
この場合は、一回で作成する方が簡単だったのは明らかですが、このスタイルは非常に軽量で、長い文字列を処理するときに理解できます。
ただし、インデントされたコードがある場合、うまく機能しません。
echo "continuation \ lines" >continuation lines
一重引用符で試し、文字列を連結します。
echo 'continuation' \
'lines'
>continuation lines
注:連結には空白が含まれます。
echo
場合の代わりに x=
、エラーが発生しますlines: command not found
。
これはおそらくあなたの質問に実際には答えませんが、とにかくそれが役に立つかもしれません。
最初のコマンドは、2番目のコマンドによって表示されるスクリプトを作成します。
3番目のコマンドは、そのスクリプトを実行可能にします。
4番目のコマンドは、使用例を提供します。
john@malkovich:~/tmp/so$ echo $'#!/usr/bin/env python\nimport textwrap, sys\n\ndef bash_dedent(text):\n """Dedent all but the first line in the passed `text`."""\n try:\n first, rest = text.split("\\n", 1)\n return "\\n".join([first, textwrap.dedent(rest)])\n except ValueError:\n return text # single-line string\n\nprint bash_dedent(sys.argv[1])' > bash_dedent
john@malkovich:~/tmp/so$ cat bash_dedent
#!/usr/bin/env python
import textwrap, sys
def bash_dedent(text):
"""Dedent all but the first line in the passed `text`."""
try:
first, rest = text.split("\n", 1)
return "\n".join([first, textwrap.dedent(rest)])
except ValueError:
return text # single-line string
print bash_dedent(sys.argv[1])
john@malkovich:~/tmp/so$ chmod a+x bash_dedent
john@malkovich:~/tmp/so$ echo "$(./bash_dedent "first line
> second line
> third line")"
first line
second line
third line
このスクリプトを本当に使用したい場合は、実行可能スクリプトをに移動~/bin
して、パスに含める方が理にかなっていることに注意してください。
textwrap.dedent
動作の詳細については、Pythonリファレンスを確認してください。
の使用法$'...'
または"$(...)"
混乱を招く場合は、(構成ごとに1つずつ)別の質問をして、まだ問題がないか確認してください。他の人がリンクされた参照を持つように、あなたが見つけたり質問したりする質問へのリンクを提供するとよいでしょう。