我想写一些预定义的文本与以下文件:

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之后没有空间,但额外的空间是如何出来的?


当前回答

这里只提一个简单的单行连接,因为它有时很有用。

# 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

其他回答

在bash脚本中,以下工作:

#!/bin/sh

text="this is line one\nthis is line two\nthis is line three"
echo -e $text > filename

另外:

text="this is line one
this is line two
this is line three"
echo "$text" > filename

Cat文件名给出:

this is line one
this is line two
this is line three

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

对于这个目的,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

但是在代码中必须使用制表符而不是空格来缩进。

我发现了更多的解决方案,因为我想有每一行适当缩进:

You may use echo: echo "this is line one" \ "\n""this is line two" \ "\n""this is line three" \ > filename It does not work if you put "\n" just before \ on the end of a line. Alternatively, you can use printf for better portability (I happened to have a lot of problems with echo): printf '%s\n' \ "this is line one" \ "this is line two" \ "this is line three" \ > filename Yet another solution might be: 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 or text='' text+="this is line one\n" text+="this is line two\n" text+="this is line three\n" printf "%b" "$text" > filename Another solution is achieved by mixing printf and sed. if something then printf '%s' ' this is line one this is line two this is line three ' | sed '1d;$d;s/^ //g' fi It is not easy to refactor code formatted like this as you hardcode the indentation level into the code. It is possible to use a helper function and some variable substitution tricks: 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"

或者用空格保持文本缩进:

#!/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

;-)