对于开源源码修改过程中的必经阶段:对源码打补丁,总是不够精通,搜索了补丁的原理的详细过程,如下:

在移植或版本升级过程中,手动比对(用比对工具)转换是很费力的事情,特别是发生变化的文件非常多的情况下,“制作补丁、打补丁”可以简化这个过程。主要用到diff和patch。在这里不会把man在线文档上所有的选项都介绍一下,那样也没有必要。在99%的时间里,我们只会用到几个选项。

1、diff

--------------------

NAME

diff - find differences between two files

SYNOPSIS

diff [options] from-file to-file

from_file to_file can be a directory.

--------------------

简单的说,diff的功能就是用来比较两个文件的不同,然后记录下来,也就是所谓的diff补丁。
语法格式:diff 【选项】 源文件(夹) 目的文件(夹),就是要给源文件(夹)打个补丁,使之变成目的文件(夹),术语也就是“升级”。
下面介绍三个最为常用选项:

-r 是一个递归选项,设置了这个选项,diff会将两个不同版本源代码目录中的所有对应文件全部都进行一次比较,包括子目录文件。

-N 选项确保补丁文件将正确地处理已经创建或删除文件的情况。

-u 选项以统一格式创建补丁文件,这种格式比缺省格式更紧凑些。

一般 -uN 是一直使用的参数,而 -r 如果是含子目录就使用,不含则不使用。

2、patch

------------------

NAME

patch - apply a diff file to an original

SYNOPSIS

patch [options] [originalfile[patchfile]]

but usually just

 patch -pnum <patchfile

带下划线的代表需要根据实际情况替换。比如 -pnum 实际使用时一般为 -p0, -p1。

------------------

简单的说,patch就是利用diff制作的补丁来实现源文件(夹)和目的文件(夹)的转换。这样说就意味着你可以由源文件(夹)――>目的文件(夹),也可以目的文件(夹)――>源文件(夹)。下面介绍几个最常用选项:

-pnum 是指查找patch文件中指定的文件时,忽略前num个目录,一个"/"为一层,详细内容下面解释。

-R 选项说明在补丁文件中的“新”文件和“旧”文件现在要调换过来了(实际上就是给新版本打补丁,让它变成老版本)

-E 选项说明如果发现了空文件,那么就删除它

3、patch文件的结构

(1)补丁头

补丁头是分别由---/+++开头的两行,用来表示要打补丁的文件。---开头表示旧文件,+++开头表示新文件。

一个补丁文件中可能包含以---/+++开头的很多节,每一节用来打一个补丁。所以在一个补丁文件中可以包含好多个补丁。

--- linux-2.6.25/arch/alpha/boot/misc.c 2010-05-06 01:56:42.565397700 -0700
+++ linux-2.6.29/arch/alpha/boot/misc.c 2010-05-06 00:51:06.000000000 -0700

(2)块

块是补丁中要修改的地方。它通常由一部分不用修改的东西开始和结束。他们只是用来表示要修改的位置。他们通常以@@开始,结束于另一个块的开始或者一个新的补丁头。

块会缩进一列,这一列是用来表示这一行是要增加还是要删除的。

+号表示这一行是要加上的。

-号表示这一行是要删除的。

没有加号也没有减号表示这里只是引用的而不需要修改。

4、-pnum

我们在生成补丁时,多是对目录进行操作,比如下面我对linux内核25和29两个版本arch目录下的文件做一个diff操作,生成的差异保存在arch.patch中:

diff -uNr linux-2.6.25/arch linux-2.6.29/arch > arch.patch

可以看到arch.patch开始位置的补丁头如下:

--- linux-2.6.25_android/arch/alpha/boot/misc.c 2010-05-06 01:56:42.565397700 -0700(黄色部分为打patch时命令会查找的文件名)
+++ linux-2.6.29_android/arch/alpha/boot/misc.c 2010-05-06 00:51:06.000000000 -0700

patch -p0 <arch.patch 代表忽略0层目录,即从当前目录中查找linux-2.6.25_android/arch/alpha/boot/misc.c,然后进行patch操作。
patch -p1 <arch.patch 代表忽略一层目录,即从从当前目录中查找arch/alpha/boot/misc.c,然后进行patch操作。为了能找到文件,当前目录应转到arch所属的目录下。
patch -p2 <arch.patch 代表忽略两层目录,即从从当前目录中查找alpha/boot/misc.c,然后进行patch操作。为了能找到文件,当前目录应转到alpha所属的目录下。
以此类推,patch的目录不限,可以指定patch的目录。

这个功能使用的情景是:打补丁时的目录结构/目录名跟现在要打补丁的目录结构/目录名不一样。
比如上面的例子,这个patch很可能是别人打的,打补丁时目录为 linux-2.6.25/arch,而本地的目录可能是linux_kernel_2625,
那打补丁时就可以进入linux_kernel_2625,用命令patch -p1 <arch.patch 忽略第一层目录即可打上补丁而无需修改自己的目录名或结构也不需要修改patch文件。

5、常用命令

(1)单个文件比较

diff –uN from-file to-file > to-file.patch //生成补丁 【因为单个文件,所以不需要-r选项。选项顺序没有关系,即可以是-uN,也可以是-Nu】

patch –p0 < to-file.patch //打补丁

patch –R –p0 < to-file.patch //去除补丁

(2)目录比较

diff –uNr from-dir to-dir > to-dir.patch //生成补丁

cd from-dir

patch –p1 < to-dir.patch //打补丁

patch –R –p1 < to-dir.patch //去除补丁

6、为内核打补丁

(1)首先是解压,因为发布的补丁文件都是使用gzip压缩的。

$gunzip ../setup-dir/ patch-2.4.21-rmk1.gz

(2)然后进入你的内核源代码目录

$cd linux-2.4.21

(3)打补丁

$patch –p1 < ../../setup-dir/patch-2.4.21-rmk1

打完补丁后,需要检查一下有没有拒绝执行的文件,即检查.rej文件的存在。使用命令:

$find -name *.rej

打补丁时候的常见错误
-------------------

当用patch命令来打一个补丁的时候,它试图以不同的方法来验证这个文件的完整性。

检查这个文件是一个有效的patch文件并且检查这些被改变周围的代码是不是和提供的
上下文相匹配。这些仅仅是patch所作的两个最基本的完整性检查。

如果patch遇到了一些看起来不正确的事情,那么它有两种选择。它可以拒绝应用这些改变并且
异常中断或者它试图找到一个方法来使patch命令仅仅做一些比较小的改变。

一个patch试图修正错误的例子就是:如果所有的上下文都匹配,被改变的行匹配,但是这些行的
行号不匹配。这是可能发生的,例如,如果patch在一个文件的中间做了一些改变,但是出于一些
原因在文件的开头处一些行被添加了进来或者被删除了。在这种情况下,一切看起来都很好,它只
是简单地上下移动一点,这时候patch通常会修正这些行号并且打上这个补丁。

任何时候,只要patch在打补丁的时候需要改动文件的一些内容,它就会告诉你说:
这个补丁打得有点儿混乱。你应该对这些改变保持一些警惕,因为即使补丁很可能被正确
地打上了,但是情况并不总是这样,有些情况下结果会是错误的。

当patch命令遇到一个变化而不能进行使用一种模糊的方法进行弥补的时候,它就会彻底地
放弃这个动作,并且留下来一个以.rej为扩展名的文件。你可以阅读这个文件来查看到底是
什么改变不能进行下去,从而在你愿意的情况下来手动修补它。

如果你的内核源代码上没有应用任何第三方的补丁,只是一些来自kernel.org的补丁,并且你打这些补丁
的顺序是正确的,而且你自己没有对这些源文件进行改动过,那么你应该就不会看到一个补丁
对这个文件的模糊的改变或者是一些拒绝消息。如果你确实看到了这些消息的话,那么将有非常高的
危险性,这说明或者是你的本地的源代码书或者是补丁文件在某些方面被玷污了。在这种情况下,你很可能
是应该重新下载这个补丁文件,如果事情仍然还是保持原样的话,那么我建议你去尝试从kernel.org上
下载一个完整的新的源代码树。

让我们来看一下补丁可能产生的更多信息。

如果patch命令停下来并且显示一个“File to patch”的提示符,那么这个时候patch命令找不到
要打补丁的文件。很可能的情况是你忘记指定-p1参数或者你处于一个错误的目录中了。更加不
常见的一种情况是,你会发现一些补丁需要使用-p0参数而不是-p1参数来打补丁(阅读这个补丁文件
应该能揭示出这些信息--如果是这样的话,这是一种创建补丁文件的人所犯的错误,但是不致命)

如果你得到信息“Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines)”,或者是一个类似
的消息,那就意味着patch命令必须调整改变的位置(在这个例子中,它需要在它想打补丁的地方移动7行来
适应这个补丁)。结果得到的文件可能正确也可能不正确,这决定于这个文件与所期望的文件不相同的原因。
这常常发生于你所要打的patch产生于一个另外一个内核版本,这个内核版本和你要打的patch所基于的内核
版本不同。

如果你得到一个类似于“Hunk #3 FAILED at 2387”之类的消息,那么这就意味着不能正确地打上这个
补丁,并且patch程序也不能模糊地通过。这将产生一个导致patch失败的.rej文件并且产生一个.orig
文件把一些不能改变的原始内容显示给你。

如果你得到的信息是:“Reversed (or previously applied) patch detected!  Assume -R? [n]”,
那么patch检测到了这个补丁文件中包含的改变已经应用在了目标文件上。如果你确实已经在此之前打了
这个补丁并且重新打补丁遇到了错误,那么你可以简单地选择[n]o并且终止这次补丁动作。如果你之前
打了补丁并且想得到打补丁以前的版本,但是忘记了指定-R参数,那么你在这里可以回答[y]es来使用patch
为你恢复它。这也可能发生在补丁文件的创建者在创建补丁文件的时候倒置了源文件和目标目录的位置,
在这种情况下从patch中revert实际上是打上了这个补丁。

一个类似于“patch: **** unexpected end of file in patch”或者“patch
unexpectedly ends in middle of line”的消息意味着patch命令对你加入到它之中的
文件觉得没有意义。或者是你的下载被打断了,你试图打上一个没有压缩的patch文件,而事前
并没有解压缩它,或者是你使用的补丁文件在传输的某个地方被一个邮件客户端或者一个邮件
传输代理给损坏了。例如,通过把一个长行分成两行。通常情况下这些警告可以通过把这两个
被分开的行合并起来来解决。

就像我上面提到的那样,如果你打的是从kernel.org得来的补丁到一个正确的版本,
并且你没有修改过源代码树,这些错误将从来不会发生。因此如果你从kernel.org来的
补丁上得来了这些错误,那么你应该很可能认为或者是你的补丁文件或者是源代码树
损坏掉了。我建议你重新开始下载一个完整的内核树以及你想要打的补丁2.6.x内核
---------

这是Linus发布的基础稳定版本.发布的最高版本是最新的。

如果发现了冲突或者严重的瑕疵,那么在这个基础上,一个-stable的修正补丁就会被发布
出来(参见下面)。一旦一个新的2.6.x的基础内核发布出来,就可以得到一个测试版本的补丁
,这个补丁基于先前的2.6.x版本内核和这个新的内核。

为了应用一个从2.6.11到2.6.12的补丁,你最好按照下面来做(注意这些补丁不能应用于2.6.x.y的内核,
而是应用在2.6.x的基础内核---如果你需要从2.6.x.y到2.6.x+1,那么你首先需要卸载掉2.6.x.y的补丁)

下面是一些例子:

#从2.6.11到2.6.12
$ cd ~/linux-2.6.11            # 切换到内核源代码目录
$ patch -p1 < ../patch-2.6.12        # 应用2.6.12补丁
$ cd ..
$ mv linux-2.6.11 linux-2.6.12        # 重命名源代码目录

# moving from 2.6.11.1 to 2.6.12
$ cd ~/linux-2.6.11.1            # 切换到内核源代码目录
$ patch -p1 -R < ../patch-2.6.11.1    # 恢复出来2.6.11.1
                    # 源代码目录现在是2.6.11
$ patch -p1 < ../patch-2.6.12        # 应用新的2.6.12补丁
$ cd ..
$ mv linux-2.6.11.1 linux-2.6.12    # 重命名源代码目录

2.6.x.y内核
-----------

带有四位数字版本号的内核是-stable的内核。他们包含了对一个给定的2.6.x内核的一些安全
问题以及发现的重要的退化的修复。

对于那些想要最近的稳定内核并且对于测试开发中的试验性的版本没有兴趣的
用户来说,我们推荐这个分支。

如果没有可用的2.6.x.y内核,那么最高数字的2.6.x内核是目前的稳定内核。

注意:维护稳定内核的团队通常会做一些增量的补丁,就像是基于最近的主流版本发布
的补丁一样。但是在下面我仅仅说明了非增量的情况。那些增量式的版本可以在下面的ftp
处找到: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/incr/.

这些补丁不是增量式的,意味着例如对于2.6.12.3补丁不能应用于2.6.12.2的内核源代码
上去,但是可以应用在2.6.12内核代码上。
因此,为了为了把2.6.12.3的补丁应用到你使用的2.6.12.2的内核源代码上,你不得不卸载掉
2.5.12.2补丁(因此你可以得到一个基础的2.6.12的内核源代码),并且应用新的2.6.12.3补丁。

下面是一个小例子:

$ cd ~/linux-2.6.12.2            # 切换到内核源代码目录
$ patch -p1 -R < ../patch-2.6.12.2    # 回归2.6.12.2补丁
$ patch -p1 < ../patch-2.6.12.3        # 应用新的2.6.12.3补丁
$ cd ..
$ mv linux-2.6.12.2 linux-2.6.12.3    # 重新命名内核源代码目录

-rc内核
-------

这些是候选的发布内核。当Linus认为目前的git(内核的源代码管理工具)内核树处于一个
健全的稳定状态足以用来测试的时候,而发布的开发内核。

这些内核是不稳定的,如果你试着运行他们应该会想到可能会不时地有问题出现。
但是这是主开发分支上的最稳定的内核,并且最终会变成下一个稳定的内核。因此
让尽可能多的人来测试它就显得格外重要。

对于那些想帮忙测试开发中的内核但是又不想跑那些试验性的东西的人来说,这将是
一个非常好的分支。(这样的人应该参照下面的关于-git和-mm内核的部分)

-rc补丁是非增量式的,他们应用于2.6.x内核上,就像上面描述的2.6.x.y内核一样。在-rcN
后缀之前的内核版本号代表了这个-rc的内核最终会变成的内核版本。

因此,2.6.13-rc5意思是这是2.6.13内核的第五个候选的发布版本,并且这个补丁应该打在
2.6.12的内核源代码上。

下面是3个关于怎样打这些补丁的例子:

# 首先是一个从2.6.12到2.6.13-rc3的例子

$ cd ~/linux-2.6.12            # 切换到2.6.12的源代码目录
$ patch -p1 < ../patch-2.6.13-rc3    # 打上2.6.13-rc3的补丁
$ cd ..
$ mv linux-2.6.12 linux-2.6.13-rc3    # 重新命名源代码目录

# 现在从2.6.13-rc3迁移到2.6.13-rc5

$ cd ~/linux-2.6.13-rc3            # 切换到2.6.12的源代码目录
$ patch -p1 -R < ../patch-2.6.13-rc3    # 卸载掉2.6.13-rc3补丁
$ patch -p1 < ../patch-2.6.13-rc5    # 应用新的2.6.13-rc5补丁
$ cd ..
$ mv linux-2.6.13-rc3 linux-2.6.13-rc5    # 重新命名源代码目录

# 最后让我们试着从2.6.12.3到2.6.13-rc5

$ cd ~/linux-2.6.12.3            # 切换到内核源代码目录
$ patch -p1 -R < ../patch-2.6.12.3    # 回返2.6.12.3补丁
$ patch -p1 < ../patch-2.6.13-rc5    # 应用新的2.6.13-rc5补丁
$ cd ..
$ mv linux-2.6.12.3 linux-2.6.13-rc5    # 重新命名源代码目录

-git内核
--------

这些是每天Linus的内核树的快照(在一个git仓库中管理着,因此得名)。

这些补丁通常每天都发布而且代表了的Linus的内核树的当前状态,由于它们是自动产生的
甚至没有任何一个光标的骚动来看它们是不是健全的,所以它们比-rc内核更具有试验性。

-git补丁不是增量的,它们或者是应用在2.6.x内核上或者是应用在一个基础的
2.6.x-rc内核上---这一点你可以从他们的名字上看出来。一个名字是2.6.12-git1的
补丁应用在2.6.12内核源代码上,一个名字为2.6.13-rc3-git2的补丁应用在2.6.13-rc3
的内核源代码上。

这里是一些怎样打这些补丁的例子:

# 从2.6.12迁移到2.6.12-git1

$ cd ~/linux-2.6.12            # 切换到内核源代码目录
$ patch -p1 < ../patch-2.6.12-git1    # 应用2.6.12-git1补丁
$ cd ..
$ mv linux-2.6.12 linux-2.6.12-git1    # 重新命名内核源代码目录

# 从2.6.12-git1迁移到2.6.13-rc2-git3

$ cd ~/linux-2.6.12-git1        # 切换到内核源代码目录
$ patch -p1 -R < ../patch-2.6.12-git1    # 回返2.6.12-git1补丁
                    # 我们现在有了一个2.6.12内核
$ patch -p1 < ../patch-2.6.13-rc2    # 打上2.6.13-rc2补丁
                    # 内核现在是2.6.13-rc2
$ patch -p1 < ../patch-2.6.13-rc2-git3    # 打上2.6.13-rc2-git3补丁
                    # 内核现在是2.6.13-rc2-git3
$ cd ..
$ mv linux-2.6.12-git1 linux-2.6.13-rc2-git3    # 重新命名内核源代码目录

-mm内核
-------

这是Andrew Morton发布的实验性的内核

-mm树作为一个新特性和实验性的补丁的实验场。一旦一个补丁在-mm中经过一段时间被证明
有价值,为了使它能包含在主流内核中,Andrew就会把它推给Linus。

尽管鼓励的方法是通过-mm树把补丁推给Linus,这个步骤并不是总被实行。子系统的维护者
(或者个人)有些时候直接把补丁推给Linus,尽管(或者之后)它们已经被它并到了-mm中并得
到了测试(或者有些时候并没有事前在-mm中得到测试)。

通常情况下你应该尽力使你的补丁通过-mm中最大程度测试后再到达主流内核中。

这个分支是一个持续的变化并且包含了一些实验性的特征,很多正在debug的补丁并不适合于
主流的内核等等。这个分支是这个文档中描述的最具有试验性的分支。

这些内核内核不适合于应用在要求稳定的系统上面,并且在运行中比其他任何的分支都可能承担
更大的风险(确信你有最新的备份---跟踪了任何试验性的内核但是甚至更多,于是达到-mm内核)。

这些内核除了包含所有的试验性的补丁以外,它们还包含了在主流-git内核发布的时候任何
可用的改变。

对-mm内核测试会得到极大的赏识,因为这个分支的总的目的就是为了在改变被加到更加稳定的
主流的Linus内核树之前,消除退化、死机、数据失败bug、build失败(以及任何通常意义上的bug)。

但是-mm的测试者应该清醒地认识到这个源代码树中的失败会比其他任何树中的都要普遍。

-mm内核并不会以一个固定的时间发布,但是通常一些-mm内核会在每一个-rc内核(通常1到3个)
发布的中间。-mm内核或者是应用于一个基础的2.6.x内核(当还没有-rc内核发布的时候)或者应用于
一个Linus -rc的内核。

这里有一个打-mm补丁的例子

# 从2.6.12到2.6.12-mm1

$ cd ~/linux-2.6.12            # 切换到2.6.12的源文件目录
$ patch -p1 < ../2.6.12-mm1        # 打一个2.6.12-mm1的补丁
$ cd ..
$ mv linux-2.6.12 linux-2.6.12-mm1    # 重新正确命名这个源文件

# 从2.6.12-mm1到2.6.13-rc3-mm3

$ cd ~/linux-2.6.12-mm1
$ patch -p1 -R < ../2.6.12-mm1        # 卸载掉2.6.12-mm1补丁
                    # 现在我们得到了一个2.6.12的源文件
$ patch -p1 < ../patch-2.6.13-rc3    # 打一个2.6.13-rc3的补丁
                    # 我们现在得到一个2.6.13-rc3的源文件
$ patch -p1 < ../2.6.13-rc3-mm3        # 打一个2.6.13-rc3-mm3的补丁
$ cd ..
$ mv linux-2.6.12-mm1 linux-2.6.13-rc3-mm3    # 重新命名源文件目录

上面总结了不同内核树的一些解释。我希望你已经明白了怎样打不同的补丁并且对你测
试内核有所帮助。

致谢列表:
Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert,
Johannes Stezenbach, Grant Coady, Pavel Machek,还有一些人我可能忘记了他们的名字,
但是他们对这篇文档进行了评论或者贡献。

diff patch制作补丁打补丁相关推荐

  1. Linux下使用diff和patch制作及打补丁(已经实践可行!)

    在做开发的过程中难免需要给内核及下载的一些源码打补丁,所以我们先学习下Linux下使用如如何使用diff制作补丁以及如何使用patch打补丁. 通过diff命令比较出新旧版本之间的差异,并以patch ...

  2. 使用diff和patch制作及打补丁

    在做开发的过程中难免需要给内核及下载的一些源码打补丁,所以我们先学习下Linux下使用如如何使用diff制作补丁以及如何使用patch打补丁. 首先介绍一下diff和patch. 1.diff --- ...

  3. linux diff patch 生成和打补丁

    通过diff工具生成补丁, patch工具打上补丁. 在使用diff之前, 你需要保留一份未修改过的源码, 然后在其它地方修改源码的一份拷贝. diff对比这两份源码生成patch. 修改过的源码必须 ...

  4. linux下diff、patch制作补丁

    http://blog.csdn.net/goldfighter/article/details/6150309 学习资料的收集比较简单,方法一类似于这种初级问题网上资料非常丰富,google或者ba ...

  5. linux利用patch和diff命令制作文件补丁

    linux利用patch和diff命令制作文件补丁 因为在 u-boot 移植过程中,有几处通用文件要修改,如果每次都要手动修改就太麻烦了.制作补丁可以解决这个问题. 学习资料的收集比较简单,方法一类 ...

  6. diff (制作补丁)和 patch(添加补丁) 的简介及简单使用

    diff是Linux系统的一个很重要的工具程序,我们通常用diff对同一软件(或程序)的不同版本的文件进行对比查看.不过,你不要用diff去比较两个完全不相干的文件,因为那样是比不出结果来的. dif ...

  7. 学习patch命令打补丁,diff命令制作补丁

    patch:通过补丁文件,来对原文件打补丁 diff:      比较两个文件,然后生成一个补丁文件 1.patch用法    patch -p[剥离层级]  <[补丁文件] 2.patch命令 ...

  8. linux内核patch文件夹,如何制作patch文件及如何打patch 附带linux打补丁命令

    对某个版本的Linux内核做了修改以后,如果希望发布出去给别人用,那么就需要制作针对此版本的patch文件.比如基于Linux-2.6.25内核 做了修改,修改后的内容放在文件夹Linux-2.6.2 ...

  9. 生成补丁 与 打补丁 diff patch

    有两个目录 每个目录中有一个相同名字的文件  但是内容 是些地方有差别,我们以此来做实验 验证diff patch 这两个命令 目录1:/you 包含file.c 这个文件比下面的file.c文件 多 ...

最新文章

  1. Redis主从复制配置
  2. 方案类:城中村社区网运营计划书-地方社区发展经典案例
  3. 安卓访问mysql的源码_【原创源码】安卓数据库简单操作demo
  4. 【数据结构总结】第一章:数据结构基本概念
  5. merge规则 python_30个Python极简代码,10分钟get常用技巧
  6. lintcode-93-平衡二叉树
  7. python的基础知识可以应用到哪方面-Python基础知识
  8. cassss服务未启动_Mysql无法启动情况下,如何恢复数据呢?
  9. Spring Bean懒加载与非懒加载
  10. 高级商务办公软件应用【1】
  11. 遗传算法matlab_通俗易懂地解释遗传算法
  12. 前端学习——页面布局
  13. 2000坐标系xy坐标几位_2000国家大地坐标系
  14. 非线性拟合matlab代码,Matlab非线性拟合
  15. html语言%3cspan%3e,比较好的网站HTML语言.doc
  16. AI-多模态-2021:ALBEF
  17. python模块,库
  18. 服务器磁盘爆满的问题定位流程与命令汇总
  19. 领导力专题︱如何培养与提升领导力
  20. 利用matlab求解非线性规划问题

热门文章

  1. python 判断子序列_LeetCode 392. 判断子序列 | Python
  2. sqlserver 班级排名_Sqlserver:班级排名问题(转发)
  3. 如何设置mysql的权限_mysql 权限控制
  4. pythonre正则表达式1012pythonre正则表达式_python re模块 正则表达式
  5. 肝了这套Python数据分析教程,进字节稳了!
  6. 一张截图,告诉你字节跳动的 Java 开发能力到底有多强...
  7. 一行代码不用写,就可以训练、测试、使用模型,这个 star 量 1.5k 的项目帮你做到...
  8. 再见,Navicat!这个Pycharm的兄弟真香!
  9. python网址在浏览器能打开_Python - Flask - 在默认浏览器中打开一个网页
  10. 吉林省计算机二级考试题型,吉林省 | 2018年上半年全国计算机二级考试报考简章...