直接回答

直接回答

在 Bash 中,分词是命令行处理中的一个步骤。来自 Bash 手册

shell 将 $IFS 的每个字符视为分隔符,并使用这些字符作为字段终止符将其他扩展的结果拆分为单词。如果 IFS 未设置,或其值恰好是 <space><tab><newline>默认值,则<space>, <tab>, and <newline>忽略先前扩展结果的开头和结尾处的序列,并且不在开头或结尾处的任何 IFS 字符序列用于分隔单词。如果 IFS 具有默认值以外的值,则只要空白字符位于 IFS 值(IFS 空白字符)中,单词开头和结尾的空白字符 space 和 tab 序列就会被忽略。 IFS 中非 IFS 空白的任何字符以及任何相邻的 IFS 空白字符共同界定字段。 IFS 空白字符序列也被视为分隔符。如果IFS的值为空,则不会发生分词。

我想重写以下示例,以便space将参数a, band之间的分隔符c替换为tabornewline

$ echo a b c
a b c

但当我按下按键时Tab,却没有任何反应。

当我点击\和时,输出中的、和return之间没有空格:abc

$ echo a\
> b\
> c
abc

为什么我不能按照引文所说的去做?

顺便说一句,没有任何结果$IFS

$ echo $IFS

答案1

换行符由 特殊处理bash,无论 的值如何IFS。换行符前的反斜杠会导致换行符被忽略。与分词无关,即使IFS设置为某个自定义值也会发生。

LESS=+/^QUOTING man bash

   A  non-quoted  backslash (\) is the escape character.  It preserves the
   literal value of the next character that follows, with the exception of
   <newline>.   If  a  \<newline>  pair  appears, and the backslash is not
   itself quoted, the \<newline> is treated as a line  continuation  (that
   is, it is removed from the input stream and effectively ignored).

您可以看到换行符上的单词分割以另一种方式发生:将换行符填充到变量中,然后echo在不引用它的情况下对该变量进行引用。

$ myvar=a$'\n'b$'\n'c
$ echo "$myvar"
a
b
c
$ echo $myvar
a b c
$ 

答案2

直接回答

未引用的命令:echo a b c,将在(元字符空间)上分割,无论IFS是什么或不是。echo: 的split 参数将用空格打印a,因为 echo 定义如下:bc

LESS=+/'^ *echo \[-neE\] \[arg ...\]' man bash

输出参数,用空格分隔,后跟换行符。

亦无$IFS参与。

所以,你引用的内容在这里没有相关性。关键部分是:

...将其他扩展的结果拆分为单词...

必须$IFS使用之前有一个扩展。
中没有任何扩展a b c

如果必须使用 $IFS 的效果,请使用不带引号的扩展:

$ var='a   b   c'
$ echo $var
a b c

但这仍然不$IFS用于输出,仅用于分割。

输出中的 IFS。

哪里$IFS有相关性(对于输出)在$*.

$ set -- a b c
$ IFS=$'\t'
$ printf '%s\n' "$*" | od -An -vtx1c
  61  09  62  09  63  0a
   a  \t   b  \t   c  \n

这是你所需要的吗?


其他事宜。

键盘选项卡

当我按下Tab键时,没有任何反应

然后同时按下CtrlV,松开,然后按下Tab

但如果没有引号,您将无法将制表符分配给变量。测试:

$ var=a    b                  ### The space represents a tab as above.
bash: b: command not found

你会需要:

$ var="a   b"                 ### The space represents a tab as above.

至少双引号。

报价 IFS

$IFS 没有任何结果:

$ echo $IFS

$IFS因为你没有引用,所以什么也没有产生$IFS。尝试:

<user>$ echo "$IFS" | sed -n l
 \t$
$
<user>$

其中有一个来自命令 echo 的新行$IFS和一个来自命令 echo 的新行。
更好地更改为 printf:

<user>$ printf '%s' "$IFS" | sed -n l
 \t$
<user>$

并使用 od:

$ printf '%s' "$IFS" | od -An -vtx1c
  20  09  0a
      \t  \n

因为我们已经有一种方法可以“查看”字符串中包含哪些字符。
我们也可以用它来“查看”几个字符串内的内容:

$ var='a b c'
$ echo "$var" | od -An -vtx1c
  61  20  62  20  63  0a
   a       b       c  \n

这不足为奇。因为这(带单引号)不应该是:

$ var='a\
> b\
> c'
$ echo "$var" | od -An -vtx1c
  61  5c  0a  62  5c  0a  63  0a
   a   \  \n   b   \  \n   c  \n

正是键入的内容。如果正确引用了 var,反斜杠就会正确显示。

引用

但用双引号引用可能会改变一些字符:

$ var="a\
> b\
> c"
$ echo "$var" | od -An -vtx1c
  61  62  63  0a
   a   b   c  \n

但是您所写的内容没有关于设置 var 或在 echo 上使用它的引号。
这在 shell 中是一条禁忌规则。请正确引用

答案3

要将空格替换为制表符,$IFS可以使用参数数组:

unset IFS
set a b c
IFS=$(printf \\t)
printf "%s\n" "$*"

了解这$IFS与拆分有关 - 它包含 shell 用于拆分列表上下文中未加引号的扩展的字符列表。你不能真正用它来代替特殊 shell 参数的特殊情况除外的字符$*。在所有其他情况下,其使用将相当于无效的明确和界定未引用的 shell 扩展的某些部分。

相关内容