Bash read忽略前导空格

Bash read忽略前导空格,bash,Bash,我有一个包含以下内容的文件a.txt aaa bbb 当我执行以下脚本时: while read line do echo $line done < a.txt > b.txt 可以看出,行的前导空格已被删除。如何保留前导空格?这里有几个问题: 除非清除了IFS,否则read会去除前导和尾随空格 echo$line字符串拆分和glob展开$line的内容,将其拆分为单个单词,并将这些单词作为单个参数传递给echo命令。因此,即使在read时间清除了IFS

我有一个包含以下内容的文件
a.txt

    aaa
    bbb
当我执行以下脚本时:

while read line
do
    echo $line
done < a.txt > b.txt

可以看出,行的前导空格已被删除。如何保留前导空格?

这里有几个问题:

  • 除非清除了
    IFS
    ,否则
    read
    会去除前导和尾随空格
  • echo$line
    字符串拆分和glob展开
    $line
    的内容,将其拆分为单个单词,并将这些单词作为单个参数传递给
    echo
    命令。因此,即使在
    read
    时间清除了IFS,
    echo$line
    仍将丢弃前导和尾随空格,并将单词之间的空格更改为单个空格字符。此外,仅包含字符
    *
    的行将展开以包含文件名列表
  • echo“$line”
    是一个显著的改进,但仍然无法正确处理
    -n
    等值,它将这些值本身视为echo参数
    printf“%s\n”“$line”
    将完全修复此问题
  • 不带
    -r
    read
    将反斜杠视为连续字符而不是文字内容,因此,除非将反斜杠折叠以转义,否则它们不会包含在生成的值中
因此:


这里有几个问题:

  • 除非清除了
    IFS
    ,否则
    read
    会去除前导和尾随空格
  • echo$line
    字符串拆分和glob展开
    $line
    的内容,将其拆分为单个单词,并将这些单词作为单个参数传递给
    echo
    命令。因此,即使在
    read
    时间清除了IFS,
    echo$line
    仍将丢弃前导和尾随空格,并将单词之间的空格更改为单个空格字符。此外,仅包含字符
    *
    的行将展开以包含文件名列表
  • echo“$line”
    是一个显著的改进,但仍然无法正确处理
    -n
    等值,它将这些值本身视为echo参数
    printf“%s\n”“$line”
    将完全修复此问题
  • 不带
    -r
    read
    将反斜杠视为连续字符而不是文字内容,因此,除非将反斜杠折叠以转义,否则它们不会包含在生成的值中
因此:


上的Bash常见问题解答条目中介绍了这一点

read命令修改读取的每一行;默认情况下,它删除所有前导和尾随空格字符(空格和制表符,或IFS中存在的任何空格字符)。如果不需要,则必须清除IFS变量:

# Exact lines, no trimming
while IFS= read -r line; do
  printf '%s\n' "$line"
done < "$file"
#线条精确,无需修剪
而IFS=读取-r行;做
printf'%s\n'$行
完成<“$file”
正如查尔斯·达菲(Charles Duffy)正确指出的那样(我没有注意到
IFS
问题);如果希望在输出中看到空格,则在使用变量时还需要引用该变量,否则shell将再次删除空格

请注意,与原始代码相比,该引用代码段中的一些其他差异

在前面链接的页面顶部的一句话中介绍了如何使用
-r
参数来读取

read的-r选项可防止反斜杠解释(通常用作反斜杠换行对,以在多行上继续)。如果没有此选项,输入中的任何反斜杠都将被丢弃。您几乎应该始终在read中使用-r选项


至于使用
printf
而不是
echo
,有点遗憾的是,
echo
的行为在所有环境中都是不可移植的一致性的,处理这些差异可能会很困难<另一方面,code>printf是一致的,可以完全可靠地使用。

上的Bash常见问题解答条目介绍了这一点

read命令修改读取的每一行;默认情况下,它删除所有前导和尾随空格字符(空格和制表符,或IFS中存在的任何空格字符)。如果不需要,则必须清除IFS变量:

# Exact lines, no trimming
while IFS= read -r line; do
  printf '%s\n' "$line"
done < "$file"
#线条精确,无需修剪
而IFS=读取-r行;做
printf'%s\n'$行
完成<“$file”
正如查尔斯·达菲(Charles Duffy)正确指出的那样(我没有注意到
IFS
问题);如果希望在输出中看到空格,则在使用变量时还需要引用该变量,否则shell将再次删除空格

请注意,与原始代码相比,该引用代码段中的一些其他差异

在前面链接的页面顶部的一句话中介绍了如何使用
-r
参数来读取

read的-r选项可防止反斜杠解释(通常用作反斜杠换行对,以在多行上继续)。如果没有此选项,输入中的任何反斜杠都将被丢弃。您几乎应该始终在read中使用-r选项


至于使用
printf
而不是
echo
,有点遗憾的是,
echo
的行为在所有环境中都是不可移植的一致性的,处理这些差异可能会很困难<另一方面,code>printf是一致的,可以完全可靠地使用。

如果不提供用于保存输入的
read
任何参数(取决于默认变量
REPLY
),则不会删除空格,并且可以省略对
IFS
的修改。也就是说,在read-r时,
;不打印“%s\n”$REPLY;完成<“$file”
我不确定;据我所知,它似乎没有被记录在案。如果您认为它是零参数,需要将行拆分为零,那么它是有意义的
# Exact lines, no trimming
while IFS= read -r line; do
  printf '%s\n' "$line"
done < "$file"