【问题标题】:Why a variable assignment replaces tabs with spaces为什么变量赋值用空格替换制表符
【发布时间】:2013-01-09 08:42:05
【问题描述】:

为什么变量赋值会在 shell 中用空格替换制表符?

$ cat tmp
a    b e    c    d
$ res=$(cat tmp)
$ echo $res
a b e c d

【问题讨论】:

    标签: bash shell variables


    【解决方案1】:

    您需要引用变量$res 以保留空格。

    $ cat file
    a       b e     c       d
    
    $ res=$(cat file)
    
    $ echo $res
    a b e c d
    
    $ echo "$res"
    a       b e     c       d
    

    来自man bashQUOTING

    引号用于去除某些字符的特殊含义 或对外壳说的话。 引号可用于禁用对特殊字符的特殊处理,以防止 保留字不会被这样识别,并防止参数扩展。

    上面 DEFINITIONS 下列出的每个元字符对 shell 都有特殊含义 如果要代表自己,必须引用。

    ...
    
    \a     alert (bell)
    \b     backspace
    \e
    \E     an escape character
    \f     form feed
    \n     new line
    \r     carriage return
    \t     horizontal tab
    \v     vertical tab
    \\     backslash
    \'     single quote
    \"     double quote
    \nnn   the eight-bit character whose value is the octal value nnn
    \xHH   the eight-bit character whose value is the hexadecimal value HH
    \cx    a control-x character
    
    ...
    

    【讨论】:

      【解决方案2】:

      丢失选项卡的不是赋值,而是调用echo 命令。

      res 被分配了一个包含制表符的值。在 shell 中编写 $res 时,这相当于在此时键入 res 变量的内容。

      所以:

      $ echo $res
      

      与以下内容相同:

      $ echo a    b e     c       d
      

      (该行中的大空格是制表符,可以通过按Ctrl+V Tab 输入)。如果您运行该命令,您还会得到:

      a b e c d
      

      所以你的问题实际上是:为什么选项卡会在命令的参数中丢失?

      答案是命令(在这种情况下为echo)永远不会看到制表符,或者实际上是空格。 Shell 将您的命令行解析为命令名称和参数列表。它使用空格(制表符和空格)将命令拆分为这些部分。然后它运行命令,将参数列表传递给它。

      所以echo 接收到的参数是列表‘a’、‘b’、‘e’、‘c’、‘d’;它不知道最初是用什么字符分隔它们的。

      然后echo 所做的是输出它的每个参数,它们之间有一个空格。因此,您看到的输出。在原始命令行使用单个空格字符分隔每个参数的情况下,输出与输入匹配,因此看起来输入中的空格也在输出中 - 但它们不是:shell 吞噬了原始空格并echo 插入了一些新的。

      引号可用于使 shell 将多个“单词”视为单个参数。例如,如果你这样做:

      $ echo a    "b    c"    d
      

      将 3 个参数传递给 echo:“a”、“b    c”和“d”。中间参数包含 4 个空格;这些被传递给echo,因此将出现在其输出中。引号外的空格由 shell 用于拆分参数,因此不会传递给echo。因此输出为:

      a b    c d
      

      要检查这种事情,使用一个命令会更清楚,该命令会准确显示它接收到的参数数量以及每个参数中的内容。这个 Perl 单行代码可以做到这一点:

      $ perl -MData::Dumper -E 'say Dumper \@ARGV' a    b    c    d
      $VAR1 = [
                'a',
                'b',
                'c',
                'd'
              ];
      
      $ perl -MData::Dumper -E 'say Dumper \@ARGV' "a    b    c    d"
      $VAR1 = [
                'a    b    c    d'
              ];
      
      $ perl -MData::Dumper -E 'say Dumper \@ARGV' a    "b    c"    d
      $VAR1 = [
                'a',
                'b    c',
                'd'
              ];
      
      $ res="a    b c     d"
      $ perl -MData::Dumper -E 'say Dumper \@ARGV' $res
      $VAR1 = [
                'a',
                'b',
                'c',
                'd'
              ];
      
      $ perl -MData::Dumper -E 'say Dumper \@ARGV' "$res"
      $VAR1 = [
                'a    b c     d'
              ];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-04
        • 2020-03-11
        • 1970-01-01
        • 1970-01-01
        • 2015-01-14
        • 2018-01-15
        • 2010-11-13
        相关资源
        最近更新 更多