この
STR="Hello\nWorld"
echo $STR
出力として生成
Hello\nWorld
の代わりに
Hello
World
文字列に改行を含めるにはどうすればよいですか?
注:この質問はechoではありません。echo -e
は知っていますが、次のような解決策を探しています。 \n
を改行として解釈する同様のオプションを持たないotherコマンドへの引数として文字列(改行を含む)を渡すことができます。
解決策は$'string'
を使うことです、例えば:
$ STR=$'Hello\nWorld'
$ echo "$STR"
Hello
World
これがBashのマニュアルページからの抜粋です。
Words of the form $'string' are treated specially. The Word expands to
string, with backslash-escaped characters replaced as specified by the
ANSI C standard. Backslash escape sequences, if present, are decoded
as follows:
\a alert (bell)
\b backspace
\e
\E an escape character
\f form feed
\n new line
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\' single quote
\" double quote
\nnn the eight-bit character whose value is the octal value
nnn (one to three digits)
\xHH the eight-bit character whose value is the hexadecimal
value HH (one or two hex digits)
\cx a control-x character
The expanded result is single-quoted, as if the dollar sign had not
been present.
A double-quoted string preceded by a dollar sign ($"string") will cause
the string to be translated according to the current locale. If the
current locale is C or POSIX, the dollar sign is ignored. If the
string is translated and replaced, the replacement is double-quoted.
Echoはとても90年代で危険をはらんでいるので、その使用は4GB以上のコアダンプをもたらすはずです。真剣に、echoの問題が、Unix標準化プロセスがついにprintf
ユーティリティを発明し、すべての問題を排除した理由でした。
だから、文字列で改行を取得する:
FOO="hello
world"
BAR=$(printf "hello\nworld\n") # Alternative; note: final newline is deleted
printf '<%s>\n' "$FOO"
printf '<%s>\n' "$BAR"
そこ! SYSVとBSDの反響はありません。すべてがきれいに印刷され、Cのエスケープシーケンスを完全にポータブルにサポートします。誰もが今printf
を使ってください、そして決して振り返らないでください。
他の答えに基づいて私がしたことは
NEWLINE=$'\n'
my_var="__between eggs and bacon__"
echo "spam${NEWLINE}eggs${my_var}bacon${NEWLINE}knight"
# which outputs:
spam
eggs__between eggs and bacon__bacon
knight
問題はシェルにはありません。問題は実際にはecho
コマンド自体、および変数の内挿を囲む二重引用符の欠如です。 echo -e
を使ってみることもできますが、それはすべてのプラットフォームでサポートされているわけではないので、移植性の観点からprintf
が推奨される理由の1つです。
シェルスクリプトに直接改行を挿入して試してみることもできます(スクリプトが現在作成しているものである場合)。そのように見えます...
#!/bin/sh
echo "Hello
World"
#EOF
または同等に
#!/bin/sh
string="Hello
World"
echo "$string" # note double quotes!
唯一の簡単な方法は、実際に変数に新しい行を入力することです。
$ STR='new
line'
$ printf '%s' "$STR"
new
line
はい、それは書くことを意味します Enter コードの必要な箇所.
new line
文字に相当するものがいくつかあります。
\n ### A common way to represent a new line character.
\012 ### Octal value of a new line character.
\x0A ### Hexadecimal value of a new line character.
しかし、それらすべては何らかのツールによる「解釈」を必要とします( POSIX printf ):
echo -e "new\nline" ### on POSIX echo, `-e` is not required.
printf 'new\nline' ### Understood by POSIX printf.
printf 'new\012line' ### Valid in POSIX printf.
printf 'new\x0Aline'
printf '%b' 'new\0012line' ### Valid in POSIX printf.
したがって、ツールは改行を含む文字列を作成する必要があります。
$ STR="$(printf 'new\nline')"
$ printf '%s' "$STR"
new
line
いくつかのシェルでは、 $' 特別なシェル展開です。 ksh93、bash、zshで動作することが知られています。
$ STR=$'new\nline'
もちろん、もっと複雑な解決策も可能です。
$ echo '6e65770a6c696e650a' | xxd -p -r
new
line
または
$ echo "new line" | sed 's/ \+/\n/g'
new
line
-e
フラグはエレガントで率直なものです。
bash$ STR="Hello\nWorld"
bash$ echo -e $STR
Hello
World
文字列が他のコマンドの出力である場合は、引用符を使用します
indexes_diff=$(git diff index.yaml)
echo "$indexes_diff"
次のように単一引用符 '...\n ...'の直前に$を付けますが、二重引用符は機能しません。
$ echo $'Hello\nWorld'
Hello
World
$ echo $"Hello\nWorld"
Hello\nWorld
私はbashの専門家ではありませんが、これは私のために働きました:
STR1="Hello"
STR2="World"
NEWSTR=$(cat << EOF
$STR1
$STR2
EOF
)
echo "$NEWSTR"
私はこれをテキストの書式設定の方が簡単だと感じました。
改行だけを必要とし、インデントを破る複数行コードを軽蔑するような気の利いた人は、次のことができます。
IFS="$(printf '\nx')"
IFS="${IFS%x}"
Bash(そしておそらく他のシェルも)はコマンド置換後のすべての末尾の改行を削除するので、printf
の文字列は改行以外の文字で終わらせ、その後それを削除する必要があります。これはまた簡単にonelinerになることができます。
IFS="$(printf '\nx')" IFS="${IFS%x}"
私はこれが1つではなく2つのアクションであることを知っていますが、私のインデントと移植性OCDは今は平和です:)私はもともと改行のみで区切られた出力を分割できるようにこれを開発し、終了文字として
\r
を使う修正を使いました。これにより、\r\n
で終わるdos出力に対しても改行分割が機能するようになります。IFS="$(printf '\n\r')"
私はここのオプションのどれにも本当に満足していませんでした。これは私のために働いたものです。
str=$(printf "%s" "first line")
str=$(printf "$str\n%s" "another line")
str=$(printf "$str\n%s" "and another line")
私のシステム(Ubuntu 17.10)では、コマンドラインから(sh
に)入力したときとsh
スクリプトとして実行したときの両方で、この例は望みどおりに動作します。
[bash]§ sh
$ STR="Hello\nWorld"
$ echo $STR
Hello
World
$ exit
[bash]§ echo "STR=\"Hello\nWorld\"
> echo \$STR" > test-str.sh
[bash]§ cat test-str.sh
STR="Hello\nWorld"
echo $STR
[bash]§ sh test-str.sh
Hello
World
これであなたの質問に答えられると思います。 (\n
の代わりに改行文字がsh
で使用されている時点など、詳細を把握しようとはしていません)。
しかし、同じスクリプトをbash
と実行したときの動作が異なり、代わりにHello\nWorld
を出力することに気付きました。
[bash]§ bash test-str.sh
Hello\nWorld
次のようにして、bash
で目的の出力を取得できました。
[bash]§ STR="Hello
> World"
[bash]§ echo "$STR"
$STR
を囲む二重引用符に注意してください。これは、保存してbash
スクリプトとして実行した場合も同じように動作します。
以下も望ましい出力を示します。
[bash]§ echo "Hello
> World"