【问题标题】:Printf example in bash does not create a newlinebash 中的 Printf 示例不创建换行符
【发布时间】:2011-02-10 05:09:54
【问题描述】:

在 bash 脚本中使用 printf,在 "\n" 之后不添加空格不会创建换行符,而添加空格会创建换行符,例如。 g.:

  1. "\n" 后面没有空格

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

    结果:

    FirstlineLastline
    
  2. "\n " 后面的空格

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

    结果:

    Firstline
     Lastline
    

问题:为什么不 1. 创建以下结果:

Firstline 
Lastline

我知道可以使用其他技术解决这个特定问题,但我想重点说明为什么 1. 不起作用。

编辑: 当使用 echo 而不是 printf 时,我得到了预期的结果,但为什么 printf 的工作方式不同?

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

结果:

    Firstline
    Lastline

【问题讨论】:

    标签: bash printf


    【解决方案1】:

    BASH 似乎正在删除尾随的换行符。 例如

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

    【讨论】:

      【解决方案2】:

      如果你添加“\r”就可以了

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

      【讨论】:

      • Windows 换行符是 \r\n,你指的是 :-?
      【解决方案3】:

      反引号运算符删除尾随的新行。参见3.4.5。命令替换http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html

      关于已编辑问题的注释

      比较:

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

      echo 命令不会将\n 视为换行符,除非您告诉他这样做:

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

      POSIX 7 指定此行为here

      [...] 与命令的标准输出,在替换结束时删除一个或多个字符的序列

      【讨论】:

      • 问题是帖子编辑部分中的示例似乎并非如此,即部分:NewLine=echo "\n"
      • 所以我猜结论是:1) 在这种情况下,Printf 的工作方式与 echo 不同,因为 echo 需要“-e”创建实际的换行符 2) 在 printf 和 echo -e 中,所有尾随换行符都将被删除,如下所述:tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html 先生的帖子。下面的丹尼斯威廉姆森也有助于指出这些问题。谢谢!
      • 除了写入临时文件或管道之外,是否有 POSIX 7 解决方法来避免这种行为(我想保留换行符)?
      【解决方案4】:

      您编辑的echo 版本将文字反斜杠-n 放入变量$NewLine,然后由您的echo -e 解释。如果你这样做了:

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

      您的结果将与案例 #1 相同。要使 以这种方式工作,您必须转义反斜杠并将整个内容放在单引号中:

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

      或双重转义:

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

      当然,你可以直接使用printf,或者你可以像这样设置你的NewLine值:

      printf "Firstline\nLastline\n"
      

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

      【讨论】:

      • 这很令人困惑,而且——如果要挑剔的地方——也是错误的。例如:在第二个代码块中,您说您转义了换行符,但实际上您只转义了反斜杠(“转义”)。
      • 很抱歉给您带来了困惑。我会尽量澄清。
      • 谢谢。对于这个答案也是如此。根据系统,无法投票是因为“它太旧了,需要改变”。
      【解决方案5】:

      我们不需要 "echo" 或 "printf" 来创建 NewLine 变量:

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

      【讨论】:

        【解决方案6】:
        $ printf -v NewLine "\n"
        $ echo -e "Firstline${NewLine}Lastline"
        
        Firstline
        Lastline
        
        $ echo "Firstline${NewLine}Lastline"
        Firstline
        Lastline
        

        【讨论】:

          【解决方案7】:

          也许人们会带着和我一样的问题来到这里: 在用 backsticks 包裹的代码中回显 \n。一个小提示:

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

          简短的回答是:

          # 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\""
          

          一个常见的问题是,如果你在代码中这样做:

          echo 'Tomato is nice'
          

          当被倒刺包围时会产生错误

          command Tomato not found.
          

          解决方法是添加另一个 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
          }
          

          现在您可以在提示符下调试您的代码:

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

          输出会很好

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

          并使用

          进行内部调试
          mecho "a string to be hacktyped"
          

          【讨论】:

            【解决方案8】:

            对于想知道如何在printf 的参数中使用换行符的人,请使用%b 而不是%s

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

            来自手册:

            %b 在相应参数中展开反斜杠转义序列

            【讨论】:

            • 这是我的解决方案,它至少从 2011 年(Bash 4.2.46)开始工作。谢谢!
            猜你喜欢
            • 2014-04-18
            • 1970-01-01
            • 2011-07-14
            • 2011-06-30
            • 1970-01-01
            • 2014-02-15
            • 1970-01-01
            • 2012-01-20
            • 1970-01-01
            相关资源
            最近更新 更多