简体   繁体   English

bash 中的 Printf 示例不创建换行符

[英]Printf example in bash does not create a newline

Working with printf in a bash script, adding no spaces after "\n" does not create a newline, whereas adding a space creates a newline, eg:在 bash 脚本中使用printf ,在"\n"之后不添加空格不会创建换行符,而添加空格会创建换行符,例如:

  1. No space after "\n" "\n"后面没有空格

    NewLine=`printf "\n"` echo -e "Firstline${NewLine}Lastline"

    Result:结果:

     FirstlineLastline
  2. Space after "\n " "\n "后的空格

    NewLine=`printf "\n "` echo -e "Firstline${NewLine}Lastline"

    Result:结果:

     Firstline Lastline

Question: Why doesn't 1. create the following result:问题:为什么不 1. 创建以下结果:

Firstline 
Lastline

I know that this specific issue could have been worked around using other techniques, but I want to focus on why 1. does not work.我知道可以使用其他技术解决这个特定问题,但我想关注为什么 1. 不起作用。

Edited: When using echo instead of printf, I get the expected result, but why does printf work differently?编辑:当使用 echo 而不是 printf 时,我得到了预期的结果,但为什么 printf 的工作方式不同?

    NewLine=`echo "\n"`
    echo -e "Firstline${NewLine}Lastline"

Result:结果:

    Firstline
    Lastline

The backtick operator removes trailing new lines.反引号运算符删除尾随的新行。 See 3.4.5.3.4.5。 Command substitution at http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html命令替换http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html

Note on edited question注意编辑的问题

Compare:相比:

[alvaro@localhost ~]$ printf "\n"

[alvaro@localhost ~]$ echo "\n"
\n
[alvaro@localhost ~]$ echo -e "\n"


[alvaro@localhost ~]$

The echo command doesn't treat \\n as a newline unless you tell him to do so: echo 命令不会将\\n视为换行符,除非您告诉他这样做:

NAME
       echo - display a line of text
[...]
       -e     enable interpretation of backslash escapes

POSIX 7 specifies this behaviour here : POSIX 7 在此处指定此行为:

[...] with the standard output of the command, removing sequences of one or more characters at the end of the substitution [...] 使用命令的标准输出,在替换结束时删除一个或多个字符的序列

Maybe people will come here with the same problem I had: echoing \\n inside a code wrapped in backsticks.也许人们会带着我遇到的同样问题来到这里:在用 backsticks 包裹的代码中回显 \\n。 A little tip:一个小技巧:

printf "astring\n"
# and 
printf "%s\n" "astring" 
# both have the same effect.
# So... I prefer the less typing one

The short answer is:简短的回答是:

# Escape \n correctly !

# Using just: printf "$myvar\n" causes this effect inside the backsticks:
printf "banana
"

# So... you must try \\n  that will give you the desired 
printf "banana\n"

# Or even \\\\n if this string is being send to another place 
# before echoing,

buffer="${buffer}\\\\n printf \"$othervar\\\\n\""

One common problem is that if you do inside the code:一个常见的问题是,如果你在代码里面做:

echo 'Tomato is nice'

when surrounded with backsticks will produce the error当被 backsticks 包围时会产生错误

command Tomato not found.

The workaround is to add another echo -e or printf解决方法是添加另一个 echo -e 或 printf

printed=0

function mecho(){
  #First time you need an "echo" in order bash relaxes.
  if [[ $printed == 0 ]]; then
    printf "echo -e $1\\\\n"
    printed=1
  else
    echo -e "\r\n\r$1\\\\n"
  fi
}

Now you can debug your code doing in prompt just:现在您可以在提示符下调试您的代码:

(prompt)$  `mySuperFunction "arg1" "etc"`

The output will be nicely输出会很好

 mydebug: a value
 otherdebug: whathever appended using myecho
 a third string

and debuging internally with并在内部调试

mecho "a string to be hacktyped"
$ printf -v NewLine "\n"
$ echo -e "Firstline${NewLine}Lastline"

Firstline
Lastline

$ echo "Firstline${NewLine}Lastline"
Firstline
Lastline

It looks like BASH is removing trailing newlines.看起来 BASH 正在删除尾随的换行符。 eg例如

NewLine=`printf " \n\n\n"`
echo -e "Firstline${NewLine}Lastline"
Firstline Lastline

NewLine=`printf " \n\n\n "`
echo -e "Firstline${NewLine}Lastline"
Firstline


 Lastline

Your edited echo version is putting a literal backslash-n into the variable $NewLine which then gets interpreted by your echo -e .您编辑的echo版本将文字反斜杠-n 放入变量$NewLine ,然后由您的echo -e解释。 If you did this instead:如果你这样做:

NewLine=$(echo -e "\n")
echo -e "Firstline${NewLine}Lastline"

your result would be the same as in case #1.您的结果将与情况 #1 相同。 To make that one work that way, you'd have to escape the backslash and put the whole thing in single quotes:要使之以这种方式工作,您必须转义反斜杠并将整个内容放在单引号中:

NewLine=$(printf '\\n')
echo -e "Firstline${NewLine}Lastline"

or double escape it:或双重逃脱它:

NewLine=$(printf "\\\n")

Of course, you could just use printf directly or you can set your NewLine value like this:当然,你可以直接使用printf或者你可以像这样设置你的 NewLine 值:

printf "Firstline\nLastline\n"

or或者

NewLine=$'\n'
echo "Firstline${NewLine}Lastline"    # no need for -e

For people coming here wondering how to use newlines in arguments to printf , use %b instead of %s :对于来这里想知道如何在printf参数中使用换行符的人,请使用%b而不是%s

$> printf "a%sa" "\n"
a\na
$> printf "a%ba" "\n"
a
a

From the manual:从手册:

%b expand backslash escape sequences in the corresponding argument %b 在相应的参数中展开反斜杠转义序列

We do not need "echo" or "printf" for creating the NewLine variable:我们不需要“echo”或“printf”来创建 NewLine 变量:

NewLine="
"
printf "%q\n" "${NewLine}"
echo "Firstline${NewLine}Lastline"

Bash delete all trailing newlines in commands substitution. Bash 删除命令替换中的所有尾随换行符。

To save trailing newlines, assign printf output to the variable with printf -v VAR要保存尾随换行符,请使用printf -v VARprintf output 分配给变量

instead of代替

NewLine=`printf "\n"`
echo -e "Firstline${NewLine}Lastline"
#FirstlineLastline

use利用

printf -v NewLine '\n'
echo -e "Firstline${NewLine}Lastline"
#Firstline
#Lastline

Explanation解释

According to bash man根据 bash 人

3.5.4 Command Substitution 3.5.4 命令替换

$(command) $(命令)

or或者

`command` `命令`

Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted . Bash通过执行命令并用命令的标准 output 替换命令替换来执行扩展,删除任何尾随换行符 Embedded newlines are not deleted, but they may be removed during word splitting.嵌入的换行符不会被删除,但它们可能会在分词过程中被删除。

So, after adding any trailing newlines, bash will delete them.因此,在添加任何尾随换行符后,bash 将删除它们。

var=$(printf '%s\n%s\n\n\n' 'foo' 'bar')
echo "$var"

output: output:

foo
bar

According to help printf根据help printf

printf [-v var] format [arguments]

If the -v option is supplied, the output is placed into the value of the shell variable VAR rather than being sent to the standard output.如果提供了 -v 选项,则 output 被放入 shell 变量 VAR 的值中,而不是发送到标准 output。

In this case, for safe copying of formatted text to the variable, use the [-v var] option:在这种情况下,为了将格式化文本安全复制到变量,请使用[-v var]选项:

printf -v var '%s\n%s\n\n\n' 'foo' 'bar'
echo "$var"

output: output:

foo
bar




Works ok if you add "\\r"如果您添加“\\r”,则可以正常工作

$ nl=`printf "\n\r"` && echo "1${nl}2"
1
2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM