本文翻译自:Multi-line string with extra space (preserved indentation)
I want to write some pre-defined texts to a file with the following: 我想使用以下内容将一些预定义的文本写入文件:
text="this is line one\n
this is line two\n
this is line three"
echo -e $text > filename
I'm expecting something like this: 我期待这样的事情:
this is line one
this is line two
this is line three
But got this: 但是得到这个:
this is line one
this is line two
this is line three
I'm positive that there is no space after each \\n
, but how does the extra space come out? 我很肯定每个\\n
后都没有空格,但是多余的空格又如何出现呢?
参考:https://stackoom.com/question/1cP5P/多行字符串-带有多余的空格-保留缩进
in a bash script the following works: 在bash脚本中,以下工作:
#!/bin/sh
text="this is line one\nthis is line two\nthis is line three"
echo -e $text > filename
alternatively: 或者:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
cat filename gives: cat文件名给出:
this is line one
this is line two
this is line three
echo
adds spaces between the arguments passed to it. echo
在传递给它的参数之间添加空格。 $text
is subject to variable expansion and word splitting, so your echo
command is equivalent to: $text
会进行变量扩展和单词拆分,因此您的echo
命令等效于:
echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n" ...
You can see that a space will be added before "this". 您可以看到在“ this”之前将添加一个空格。 You can either remove the newline characters, and quote $text
to preserve the newlines: 您可以删除换行符,并引用$text
以保留换行符:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
Or you could use printf
, which is more robust and portable than echo
: 或者,您可以使用printf
,它比echo
更加健壮和可移植:
printf "%s\n" "this is line one" "this is line two" "this is line three" > filename
In bash
, which supports brace expansion, you could even do: 在支持大括号扩展的bash
,您甚至可以执行以下操作:
printf "%s\n" "this is line "{one,two,three} > filename
Heredoc sounds more convenient for this purpose. 为此,Heredoc听起来更方便。 It is used to send multiple commands to a command interpreter program like ex or cat 它用于将多个命令发送到命令解释程序,例如ex或cat
cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
The string after <<
indicates where to stop. <<
之后的字符串表示在何处停止。
To send these lines to a file, use: 要将这些行发送到文件,请使用:
cat > $FILE <<- EOM
Line 1.
Line 2.
EOM
You could also store these lines to a variable: 您还可以将这些行存储到变量中:
read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM
This stores the lines to the variable named VAR
. 这会将行存储到名为VAR
的变量中。
When printing, remember the quotes around the variable otherwise you won't see the newline characters. 打印时,请记住变量周围的引号,否则您将看不到换行符。
echo "$VAR"
Even better, you can use indentation to make it stand out more in your code. 更好的是,您可以使用缩进使其在代码中更加突出。 This time just add a -
after <<
to stop the tabs from appearing. 这次只需在<<
之后添加-
即可阻止标签显示。
read -r -d '' VAR <<- EOM
This is line 1.
This is line 2.
Line 3.
EOM
But then you must use tabs, not spaces, for indentation in your code. 但是,您必须在代码中使用制表符(而不是空格)来缩进。
I've found more solutions since I wanted to have every line properly indented: 自从我希望正确缩进每一行以来,我发现了更多解决方案:
You may use echo
: 您可以使用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. 如果将"\\n"
放在行末\\
之前,则不起作用。
Alternatively, you can use printf
for better portability (I happened to have a lot of problems with echo
): 另外,您可以使用printf
以获得更好的可移植性(我碰巧对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
. 通过混合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
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"
If you're trying to get the string into a variable, another easy way is something like this: 如果您尝试将字符串放入变量中,则另一种简单的方法是这样的:
USAGE=$(cat <<-END
This is line one.
This is line two.
This is line three.
END
)
If you indent your string with tabs (ie, '\\t'), the indentation will be stripped out. 如果使用制表符(即'\\ t')缩进字符串,则缩进将被删除。 If you indent with spaces, the indentation will be left in. 如果缩进空格,则缩进将保留。
NOTE: It is significant that the last closing parenthesis is on another line. 注:这是显著的最后一个右括号是另一条线路上。 The END
text must appear on a line by itself. END
文本必须单独显示在一行上。