我想使用以下内容将一些预定义的文本写入文件:
text="this is line one\n
this is line two\n
this is line three"
echo -e $text > filename
我期待这样的事情:
this is line one
this is line two
this is line three
但得到了这个:
this is line one
this is line two
this is line three
我很肯定每个\n
之后没有空格,但额外空间是如何产生的?
答案 0 :(得分:501)
Heredoc听起来更方便。它用于向命令解释程序发送多个命令,如 ex 或 cat
cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
<<
后的字符串表示停止的位置。
要将这些行发送到文件,请使用:
cat > $FILE <<- EOM
Line 1.
Line 2.
EOM
您还可以将这些行存储到变量中:
read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM
这会将行存储到名为VAR
的变量。
打印时,请记住变量周围的引号,否则您将看不到换行符。
echo "$VAR"
更好的是,您可以使用缩进使其在代码中更突出。这次只需在-
之后添加<<
即可停止显示标签。
read -r -d '' VAR <<- EOM
This is line 1.
This is line 2.
Line 3.
EOM
但是你必须在代码中使用制表符而不是空格来缩进。
答案 1 :(得分:117)
如果您正在尝试将字符串转换为变量,另一种简单的方法是这样的:
USAGE=$(cat <<-END
This is line one.
This is line two.
This is line three.
END
)
如果您使用制表符缩进字符串(即&#39; \ t&#39;),则会删除缩进。如果缩进空格,缩进将保留。
注意: 显着,最后一个右括号在另一行。 END
文字必须单独显示在一行上。
答案 2 :(得分:67)
echo
在传递给它的参数之间添加空格。 $text
受变量扩展和分词限制,因此echo
命令等同于:
echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n" ...
您可以看到在“this”之前添加了一个空格。您可以删除换行符,并引用$text
以保留换行符:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
或者你可以使用printf
,它比echo
更健壮,更便携:
printf "%s\n" "this is line one" "this is line two" "this is line three" > filename
在支持大括号扩展的bash
中,你甚至可以这样做:
printf "%s\n" "this is line "{one,two,three} > filename
答案 3 :(得分:35)
在bash脚本中,以下工作:
#!/bin/sh
text="this is line one\nthis is line two\nthis is line three"
echo $text > filename
<强>可替换地:强>
text="this is line one
this is line two
this is line three"
echo "$text" > filename
cat filename给出:
this is line one
this is line two
this is line three
答案 4 :(得分:31)
我找到了更多解决方案,因为我想让每一行都正确缩进:
您可以使用echo
:
echo "this is line one" \
"\n""this is line two" \
"\n""this is line three" \
> filename
如果您将"\n"
放在\
之前的行末,则无效。
或者,您可以使用printf
来提高可移植性(我在echo
时遇到了很多问题):
printf '%s\n' \
"this is line one" \
"this is line two" \
"this is line three" \
> filename
另一个解决方案可能是:
text=''
text="${text}this is line one\n"
text="${text}this is line two\n"
text="${text}this is line three\n"
printf "%b" "$text" > filename
或
text=''
text+="this is line one\n"
text+="this is line two\n"
text+="this is line three\n"
printf "%b" "$text" > filename
通过混合printf
和sed
来实现另一种解决方案。
if something
then
printf '%s' '
this is line one
this is line two
this is line three
' | sed '1d;$d;s/^ //g'
fi
在将缩进级别硬编码到代码中时,重构像这样格式化的代码并不容易。
可以使用辅助函数和一些变量替换技巧:
unset text
_() { text="${text}${text+
}${*}"; }
# That's an empty line which demonstrates the reasoning behind
# the usage of "+" instead of ":+" in the variable substitution
# above.
_ ""
_ "this is line one"
_ "this is line two"
_ "this is line three"
unset -f _
printf '%s' "$text"
答案 5 :(得分:2)
我来听是在寻找这个答案,但也想将其传递给另一个命令。给定的答案是正确的,但如果有人要传送它,则需要像这样在多行字符串之前传送它
echo | tee /tmp/pipetest << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
这将使您拥有多行字符串,但也可以将其放在后续命令的标准输入中。
答案 6 :(得分:1)
以下是我为变量分配多行字符串的首选方式(我认为它看起来不错)。
read -r -d '' my_variable << \
_______________________________________________________________________________
String1
String2
String3
...
StringN
_______________________________________________________________________________
两种情况下的下划线数目相同(此处为80)。
答案 7 :(得分:1)
如果您将其放置如下,它将起作用:
AA='first line
\nsecond line
\nthird line'
echo $AA
output:
first line
second line
third line
答案 8 :(得分:0)
仅提及简单的单行连接,因为有时它会很有用。
# for bash
v=" guga "$'\n'" puga "
# Just for an example.
v2="bar "$'\n'" foo "$'\n'"$v"
# Let's simplify the previous version of $v2.
n=$'\n'
v3="bar ${n} foo ${n}$v"
echo "$v3"
您会得到类似的东西
bar foo guga puga
所有开头和结尾的空格都将保留用于
echo "$v3" > filename
答案 9 :(得分:0)
有很多方法可以做到这一点。对我而言,将缩进的字符串管道输送到 sed 效果很好。
printf_strip_indent() {
printf "%s" "$1" | sed "s/^\s*//g"
}
printf_strip_indent "this is line one
this is line two
this is line three" > "file.txt"
此答案基于 Mateusz Piotrowski 的答案,但略有改进。
答案 10 :(得分:0)
或者保持文本用空格缩进:
#!/bin/sh
sed 's/^[[:blank:]]*//' >filename <<EOF
this is line one
this is line two
this is line three
EOF
相同但使用变量:
#!/bin/sh
text="$(sed 's/^[[:blank:]]*//' << whatever
this is line one
this is line two
this is line three
)"
echo "$text" > filename
;-)