Bash:将一个简短的文本文件读取到变量会丢失最后一个空行

时间:2018-04-23 11:55:15

标签: bash

我有一个脚本可以处理来自慢速大容量存储器的大量小文件。

出于性能原因,我将文件读入变量,然后使用此变量进行所有处理。这允许我只读取一次文件。

这很有效,除非最后一行是空的,那么变量将比文件短一行,见下面的简化示例。

有没有办法将文件末尾的空行读取到变量?

$ rm -f /tmp/a ; for i in $(seq 3) ; do echo $i >> /tmp/a ; done
$ cat /tmp/a
1
2
3
$ wc -l /tmp/a
3 /tmp/a
$ a="$(cat /tmp/a)"
$ echo "$a"
1
2
3
$ echo "$a" | wc -l
3

$ rm -f /tmp/b ; for i in $(seq 3) ; do echo $i >> /tmp/b ; done
$ echo >> /tmp/b # ADD EXTRA EMPTY LINE TO THE END
$ cat /tmp/b
1
2
3

$ wc -l /tmp/b
4 /tmp/b
$ b="$(cat /tmp/b)"
$ echo "$b"
1
2
3
$ echo "$b" | wc -l
3

1 个答案:

答案 0 :(得分:6)

$(command) 删除所有尾随换行符。来自bash man page

  

命令替换允许输出命令来替换命令名称。有两种形式:

`command`
     

$(cat file)
     

Bash通过执行命令并使用命令的标准输出替换命令替换来执行扩展,删除任何尾随换行符。嵌入的换行不会被删除,但在分词时可能会被删除。命令替换$(< file)可以替换为等效但更快mapfile

使用$ mapfile b < /tmp/b $ printf '%s' "${b[@]}" 1 2 3 $ printf '%s' "${b[@]}" | wc -l 4 在保留换行符的同时读取整个文件。它将每一行读入一个数组。

echo

避免printf '%s',这会增加额外的换行符。 printf -v没有这样做,所以你得到了数组中的确切内容。

如果不需要数组,可以使用$ mapfile b < /tmp/b $ printf -v b '%s' "${b[@]}" $ printf '%s' "$b" 1 2 3 $ printf '%s' "$b" | wc -l 4 将其展平为单个字符串,同时保留换行符。

class temp {

private :
    char * name;
public :
    temp(char * temp_name){

        strcpy(name,temp_name);
    cout << "Created"<<name<<endl;

    }
    ~temp(){
        cout<< "Destoyed"<<name<<endl;

    }
};
int main() {
class temp person1("Jack");
class temp haha("Katy");
    return 0;
}
  

出于性能原因,我将文件读入变量,然后使用此变量进行所有处理。这允许我只读取一次文件。

这可能是过早优化。从磁盘读取文件后,操作系统会将其保留在缓存中。重新读取仍在缓存中的文件非常快。