理解 CRLF,LF

CRLF, LF 是用来表示文本换行的方式。CR(Carriage Return) 代表回车,对应字符 '\r';LF(Line Feed) 代表换行,对应字符 '\n'。由于历史原因,不同的操作系统文本使用的换行符各不相同。主流的操作系统一般使用CRLF或者LF作为其文本的换行符。其中,Windows 系统使用的是 CRLF, Unix系统(包括Linux, MacOS近些年的版本) 使用的是LF。

系统间的这个差异给跨平台协作开发和跨平台运行带来很多不方便的地方。最近写的代码就遇到了这个问题。下面是一段按行读取配置文件的 Golang 代码,在读取一行字符之后,去掉开头结尾的换行符与空格。我是这样写的:

fun InterpretQueryLine(data []byte) {
    str_line := strings.Trim(string(data), " \n")
    // ...
}

本来在自己的 Ubuntu 系统上跑的很好,觉得没bug就提交了。然而,同事使用的是Windows系统,他编译之后怎么跑都不正常。由于我对 Golang 不熟悉,调试了很久才发现是换行符的问题。在Windows系统上换行符是CRLF, \r\n两个字符,只删除\n是不够的。所以在读取文件的时候一定要小心跨平台。

除了上面的问题,我们平常受到换行符问题的困扰更多来自协作开发工具,比如Git。有时候我们只改了源码中的一行,但提交的时候发现整个文件都被修改了。有时候拉取最新的分支,明明改动不大,但是在与本地合并的时候整个文件都是冲突。这些问题不会导致严重的错误,但是会给开发带来非常大的不方便。

下面介绍两个 Git 中换行符相关的处理方式:

这里先指定两个非官方的概念,方便后面解释与描述:(重要,否则后面看不懂)

  1. 标准化 指在提交代码到git数据库(本地库) 中将文本文件中的换行符CRLF转为LF的过程
  2. 转换 指在检出Git数据库代码过程中将文本文件中的换行符LF转换为CRLF的过程

core.autocrlf & core.safecrlf

Git 提供了一个名为 core.autocrlf 的配置,可以自动完成标准化与转换。它的设置方式如下:

git config --global core.autocrlf  [true | input | false]  # 全局设置
git config --local core.autocrlf  [true | input | false] # 针对本项目设置
  • true 自动完成标准化与转换
  • input 只做标准化操作,不做转换操作
  • false 提交与检出的代码都保持文件原有的换行符不变

  1. CRLF 与 LF 混合的文本文件不受此配置控制。
  2. Git 安装后默认为 false

所以,一种规范换行符的方式是这样的: 使用 Windows 系统的开发者设置:

git config --global core.aurocrlf true

使用 Linux/MacOS 的开发者设置:

git config --global core.autocrlf input

由于没有一个绝对有效的算法来判断一个文件是否为文本,所以Git 提供了一项禁止/警告不可逆转换的配置来防止错误的标准化与转换。它主要是影响到多种换行符混合的文件,我们可以手动将其转换为同一种换行符:

git config --global core.safecrlf [true | false | warn]
  • true 禁止提交混合换行符的文本文件(git add 的时候会被拦截,提示异常)
  • warn 提交混合换行符的文本文件的时候发出警告,但是不会阻止 git add 操作
  • false 不禁止提交混合换行符的文本文件(默认配置)

.gitattributes 文件

core.autocrlf 的配置依赖于每一位参与项目的开发机器上的配置,这很难确保每个人都能正确配置。于是在规范项目中的换行符方面,还有一套添加配置文件的方案。在项目的根目录下可以添加一个.gitattributes 文件。它的优先级高于core.autocrlf的设置,可以覆盖core.autocrlf的。它类似于 .gitignore 文件,随提交修改生效,一个项目中可以维持一份相同的配置。所以,它能够避免每个开发人员配置不同的问题。

.gitattributes文件的功能不只有配置换行符,所以它的配置相对复杂一下。详细的说明文档可以参考 地址。这里只针对换行符的配置做一下简单的介绍:

每行基本形式:

filter attr1 attr2 ....

filter 代表匹配文件的通配符,在它后面跟着相应的属性,用空格间隔。

filter 的选项比较简单,常见的:

* 匹配所有文件
*.txt  匹配文件名以txt结尾的文件

attr的选择比较多,其中与换行符相关的属性只有几条:

  • text
    • text 自动完成标准化与转换
    • -text 不执行标准化与转换
    • text=auto 根据 Git 决定是否需要执行标准化与转化
    • 不设置 使用core.autocrlf配置决定是否执行标准化与转换
  • eol
    • eol=lf 强制完成标准化,不执行转换(相当于指定转换为LF格式)
    • eol=crlf 强制完成标准化,指定转换为CRLF格式
  • binary
    • binary 二进制文件不参与标准化与转换
    • 不设置 由 Git 决定是否为二进制文件

text 设置的时候,转换自动转换到对应平台的换行符 行号高的设置会覆盖行号低的设置

这里给出一个简单的例子来说明一下:

*         text=auto
# These files are text and should be normalized (convert crlf => lf)
*.cs      text
*.xaml    text
*.csproj  text
*.sln     text
*.tt      text
*.ps1     text
*.cmd     text
*.msbuild text
*.md      text

# Images should be treated as binary
# (binary is a macro for -text -diff)
*.png     binary
*.jepg    binary

*.sdf     binary

除了下面匹配到的文件,剩下的依赖Git 决定是否参与标准化与转换。上面一段是参与标准化与转换的文件;下面一段是不参与标准化与转换的文件;

其实,在文件里只有下面这行配置的时候,就相当于根据操作系统自动填入 core.autocrlf 的设置。

* text=auto

所以,这里推荐使用.gitattributes来规范项目中换行符。简单,方便,灵活。

参考文章:

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3ld8ip2y3rsw8

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

挖洞经验 | 命令注入突破长度限制

0x01 背景 很多时候,在我们历经千辛万苦挖掘出一个漏洞或者找到一个利用点的时候,却因为一些egg hurt的限制,导致get shell或者send pay...

23610
来自专栏阿杜的世界

Spring Boot:定制URL匹配规则

构建web应用程序时,并不是所有的URL请求都遵循默认的规则。有时,我们希望RESTful URL匹配的时候包含定界符“.”,这种情况在Spring中可以称之为...

1063
来自专栏owent

libcopp更新 (merge boost 1.59 context)

这个框架的上下文部分是使用了boost.context,但是从开始写libcopp到现在,boost.context也更新了几个版本。而之前几次merge基本都...

792
来自专栏ImportSource

并发编程-什么是线程安全?

定义“线程安全”这个概念是一个非常复杂的事情。越是正式而严肃的描述它越是复杂难懂,不仅没办法提供一些实际的指导,而且还没法有一个直观的理解。还有一些不太正式的描...

3697
来自专栏java一日一条

Java高效并发之乐观锁悲观锁、(互斥同步、非互斥同步)

首先我们理解下两种不同思路的锁,乐观锁和悲观锁。 这两种锁机制,是在多用户环境并发控制的两种所机制。下面看百度百科对乐观锁和悲观锁两种锁机制的定义:

1533
来自专栏coding for love

在线商城项目08-数据库创建和商品集合的创建

因为six_tao中没有任何内容。我们需要为其创建一个集合或者插入文档,数据库才会显示。例如:

764
来自专栏嵌入式程序猿

Polyspace不认识Interrupt,肿么办?

曾经在公众号中介绍过优秀的软件验证工具Polyspace,有好多猿友在交流群里咨询这个软件的问题,今天我们就典型的如何处理中断来给大家介绍下。 ...

2954
来自专栏coding for love

在线商城项目11-商品列表页的排序实现

请求后台接口会带上三种排序参数default,priceDown和priceUp。另外,如果不带参数,我们默认排序也是default。 这里,我们做一个简单的...

642
来自专栏Java后端技术栈

Java多线程编程-(1)-线程安全和锁Synchronized概念

(1)在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单位都是进程。

803
来自专栏编程

PHP7 下的协程实现

前言 相信大家都听说过『协程』这个概念吧。 但是有些同学对这个概念似懂非懂,不知道怎么实现,怎么用,用在哪,甚至有些人认为yield就是协程! 我始终相信,如果...

2908

扫码关注云+社区