0%

more - 多多益善

more功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上。 more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会往回(back)一页显示,而且还有搜寻字串的功能 。more命令从前向后读取文件,因此在启动时就加载整个文件。

在查阅文件的时候,我们说过可以用cat命令,不过这个是入门级别的,但凡用了几天Linux的,基本不太会再使用cat,而是另外两个指令,more或者less。这次说一下more,more是在文件的内容一个屏幕装不小的时候使用的。而less是more的升级版本,稍后会介绍。

more : 文件内容一屏幕装不下的时候使用的

看看为什么用less命令吧。

more - file perusal filter for crt viewing

看不懂,什么是CRT,莫慌,关于more的解释主要针对在上古年代的计算机,你不理解crt也没有关系,毕竟现在已经是Retina的年代了。

命令格式

less的命令格式与cat一样,可以直接跟上文件名,如下:

1
less [参数] 文件

其中的参数如下所示:

  • +n 从笫n行开始显示
  • -n 定义屏幕大小为n行
  • +/pattern 在每个档案显示前搜寻该字串(pattern),然后从该字串前两行之后开始显示
  • -c 从顶部清屏,然后显示
  • -d 提示“Press space to continue,’q’ to quit(按空格键继续,按q键退出)”,禁用响铃功能
  • -l 忽略Ctrl+l(换页)字符
  • -p 通过清除窗口而不是滚屏来对文件进行换页,与-c选项相似
  • -s 把连续的多个空行显示为一行
  • -u 把文件内容中的下画线去掉

一起看看下面的实例吧,这里以文件/etc/services为例:

这个文件的开始信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# /etc/services:
# $Id: services,v 1.55 2013/04/14 ovasik Exp $
#
# Network services, Internet style
# IANA services version: last updated 2013-04-10
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, most entries here have two entries
# even if the protocol doesn't support UDP operations.
# Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
# are included, only the more common ones.
#
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]

tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp

+n 从第n行开始显示

接下来的命令从第10行开始显示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ more +10 /etc/service

# Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
# are included, only the more common ones.
#
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]

tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
systat 11/udp users
daytime 13/tcp
daytime 13/udp
qotd 17/tcp quote
qotd 17/udp quote

可以看到前面的10行是没有显示的。

-n 定义屏幕大小为n行

这里的含义为定义输出的内容为10行,你的屏幕可能足够大,不过显示的内容只有n行,如下:只显示10行的内容,此时终端可能还会残留以前的内容:

1
2
3
4
5
6
7
8
9
10
11
$ more -10 /etc/services
# /etc/services:
# $Id: services,v 1.55 2013/04/14 ovasik Exp $
#
# Network services, Internet style
# IANA services version: last updated 2013-04-10
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, most entries here have two entries
# even if the protocol doesn't support UDP operations.
# Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports

可以关注一下,此时每次显示的只有10行。

+/pattern 搜寻字符串(pattern)

这个参数用于在文件中搜索字符串pattern,然后在该字符串的前两行之前开始显示。比如搜索number,会显示以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ more +/number /etc/services
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, most entries here have two entries
# even if the protocol doesn't support UDP operations.
# Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
# are included, only the more common ones.
#
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]

tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
systat 11/udp users
daytime 13/tcp
......

可以留意,此时显示的内容,第三行即包含搜索的字符串。

其他

除以上介绍的以外,还有比较容易理解的以下参数:

  • -c 从顶部清屏,然后显示
  • -p 通过清除窗口而不是滚屏来对文件进行换页,与-c选项相似
  • -s 把连续的多个空行显示为一行
  • -u 把文件内容中的下画线去掉

Linux nice命令

.. note::

桃李春风一杯酒,江湖夜雨十年灯。

  • 黄庭坚· 《寄黄几复》

Linux nice命令可以通过修改优先级来执行程序,如果单纯输入nice,未指定程序,则会打印出目前的排程优先序,默认的数值为0,范围为最高优先级的 -20到 最低优先级的19。

所谓的优先序就是优先执行的概念,优先级越高,获得CPU的时间和顺序也会越提前。

官方定义为:

nice - run a program with modified scheduling priority

语法

使用方法如下:

1
$ nice [OPTION] [COMMAND [ARG]...]

参数的话,只有一个,如下:

  • -n, --adjustment=N 调整执行的优先序 (默认为 10)

实例

设置ls的优先级,如下将设置ls的优先级加10

1
$ nice ls

下面的就是把ls命令的优先级加5

1
$ nice -n 5 ls

设置程序运行时的优先级实例

下面通过几个操作来看一下nice的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ vim &

$ nice vi

$ nice vim &

$ nice -n 5 vim &

# 查看进程状态 其中PRI即为优先级情况,可以看到几个进程是不同的。
$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 8 7 0 80 0 - 6406 - tty1 00:00:02 bash
0 T 1000 251 8 0 75 42967291 - 15927 - tty1 00:00:00 vim
0 T 1000 319 8 0 65 42967281 - 15927 - tty1 00:00:00 vi
0 T 1000 374 8 0 65 42967281 - 15927 - tty1 00:00:00 vim
0 T 1000 415 8 2 70 42967286 - 15927 - tty1 00:00:00 vim
0 R 1000 456 8 0 80 0 - 4983 - tty1 00:00:00 ps

git好习惯

正确的版本控制系统的使用方法是,一次提交只干一件事情:或是完成了一个新功能,或是修改了一个bug,或是写完了一节的内容,或是添加了一副图片,就执行一次提交,千万不要下班了才想起来要提交,那样的话版本控制系统就被降格为文件备份系统了。

Git的命令行加入了大量的人性化设计,包括命令补全、彩色字符输出等。

Git的智能更体现在它的人性化设计上,它能够实时地显示完成的进度,因为Git的智能协议源于会话过程中在客户端和服务器端各自启用了一个会话的角色,用于按需传输和获取进度。

C语言函数调用三种方式–传值调用–引用调用和传地址调用

三种调用方式

传值

是把实参的值赋值给行参,那么对行参的修改,不会影响实参的值。
从函数调用的角度理解:
函数参数压栈的是参数的副本。任何的修改是在副本上作用,没有作用在原来的变量上。

传地址

是传值的一种特殊方式,只是他传递的是地址,不是普通的如int,那么传地址以后,实参和行参都指向同一个对象。
从函数调用的角度理解:
压栈的是指针变量的副本。当你对指针解指针操作时,其值是指向原来的那个变量,所以对原来变量操作。

传引用—c中没有,C++中才有的

真正的以地址的方式传递参数,传递以后,行参和实参都是同一个对象,只是他们名字不同而已,对行参的修改将影响实参的值.。
从函数调用的角度理解:
压栈的是引用的副本。由于引用是指向某个变量的,对引用的操作其实就是对他指向的变量的操作。

函数参数传递机制的基本理论

函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。 以下讨论称调用其他函数的函数为主调函数,被调用的函数为被调函数。
值传递(pass-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

C语言中的函数参数传递机制

在C语言中,值传递是唯一可用的参数传递机制。但是据笔者所知,由于受指针变量作为函数参数的影响,有许多朋友还认为这种情况是引用传递。这是错误的。请看下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <stdlib.h>

void pass_by_value(int a,int b);
void pass_by_address(int *pa,int *pb);
//pass_by_reference(int &ra,int &rb);

int main(void)
{
int a = 1;
int b = 2;

pass_by_value(a,b);
printf("%s:pass by value :a = %d, b = %d\n",__func__,a,b);

pass_by_address(&a,&b);
printf("%s:pass by address :a = %d, b = %d\n",__func__,a,b);

// pass_by_reference(a,b);
// printf("%s:pass by reference :a = %d, b = %d\n",__func__,a,b);

return 0;
}

void pass_by_value(int x,int y)
{
int tmp;
tmp = y;
y = x;
x = tmp;
printf("%s:pass by value: x = %d,y = %d\n",__func__,x,y);
}

void pass_by_address(int *px,int *py)
{
int tmp = *px;
*px = *py;
*py = tmp;
printf("%s:pass by address: *px = %d,*py = %d\n",__func__,*px,*py);
}
#if 0
pass_by_reference(int &rx,int &ry)
{
int tmp = rx;
rx = ry;
ry = tmp;
printf("%s:pass by reference: x = %d,y = %d\n",__func__,rx,ry);
}
#endif
  • pass_value(p1, p2)语句包含的意思是p1=a,p2=b;只是把a和b的值copy了一份给他们。
  • pass_address(*p1, *p2)语句包含的意思是p1=&a,p2=&b;是把a和b的地址值copy了一份给他们。

实参和形参

形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。

实参出现在主调函数中,进入被调函数后,实参变量也不能使用。

形参和实参的功能是作数据传送。发生函数调用时, 主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。

  • 形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。
  • 实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。
  • 实参和形参在数量上,类型上,顺序上应严格一致, 否则会发生“类型不匹配”的错误。
  • 函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。

C语言中鲜为人知的“三字母词”

在ANSI标准中,定义了“三字母词”,或者成为“三联符序列”,英文为”trigraph sequences“。目的主要是为了在一些特定的字符集中,比如一些七位代码集中,解决一些特定字符的输入问题。

也许是由于这些字符集我们基本上用不到,所以在大多数C语言的书籍中,我们都看不到对“三字母词”的讲解。这里资料来源于参考ANSI C99标准(即传说中的《American National Standards Institute for Programming Languages-C》 1999年,我们习惯简称为“C99”)。

截止到现在,“三字母词”有且仅有9个,分别为:

三字母词 对应的字符
??= #
??( [
??) ]
??< {
??> }
??/ \
??!
??’ ^
??- ~

就这9个,没有其他的三字母词。源代码中的“三字母词”,在编译阶段会被替换为“对应的字符”。对于以“?”开头的字符序列,如果不能与上面9个匹配,编译器将保持原状;一旦匹配,编译器就会做替换。

编译时可能需要加上选项-trigraphs。输出为:

其中缺的那项为\。并且会在编译的时候报警:

1
warning: unknown escape sequence: ‘\040’ [enabled by default]

因为我们知道\后面需要跟上有意义的转义字符才可以,比如n为换行等。

Python参考书

基础

进阶

专题

类和实例

类和对象是面向对象编程的两个主要方面。

其中类创建一个新类型,而对象是这个类的实例,类使用class关键字创建。

__init__方法属于Python语言的构造函数,一个类只能有一个init方法,用于初始化类及其变量。

类的属性和方法

  • 类的方法:在类的内部使用def关键字定义一个方法,与一般函数不同,需要包含self参数,且为第一个参数
  • 类的私有方法:在类的内部使用,命名格式为__private_method,以两个下划线开始,不能在类的外部调用,只能在内部调用
  • 类的私有属性:在类的内部使用,也是以两个下划线开头

类的动态属性

如果不希望类的某些属性被悄悄滴访问、赋值和修改,希望在被访问、赋值和修改的时候能得到一些通知,这时可以使用函数property,函数原型为:

1
property([fget[,fset[,fdel[,doc]]]])

有两种方法可以完成这个工作,分别如下所示,其中第二种相对而言更加灵活、方便和简单,推荐使用。

使用类的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MyClass(object):
def __init__(self):
self._param = None

def getParam(self):
print('get param : %s' % self._param)
return self._param

def setParam(self, value):
print('set param : %s' % self._param)
self._param = value

def delParam(self):
print('del param : %s' % self._param)
del self._param

parameter = property(getParam, setParam, delParam)


if __name__ == '__main__':
cls = MyClass()
cls.parameter = 1024
print('current param : %s ' % cls.parameter)
del cls.parameter

使用@property访问类的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class MyClass(object):
def __init__(self):
self._param = None

@property
def param(self):
print('get param : %s' % self._param)
return self._param

@param.setter
def param(self, value):
print('set param : %s' % self._param)
self._param = value

@param.deleter
def param(self):
print('del param : %s' % self._param)
del self._param


if __name__ == '__main__':
cls = MyClass()
cls.param = 1024
print('current param : %s ' % cls.param)
del cls.param

Python 注释

Python的注释方法如下:

  • 使用#开头
  • 使用三个单引号’’’ 主要用在块注释上
  • 使用三个双引号””” 主要用在块注释上

lambda表达式

lambda是一个表达式,而不是一个语句,它能够出现在Python语法不允许def出现的地方。

lambda可以用来编写简单的函数,而def用来处理更强大的任务。

比如下面的例子:

1
2
3
4
5
6
7
8
add1 = lambda x,y : x + y
multi2 = lambda x,y : x * y

x = 2
y = 3
print('x = 2 , y =3')
print('x+y = ',add1(x,y))
print('x*y = ',multi2(x,y))

从上面的代码可以看出,labmda表达式是为了减少单行函数的定义而存在的。

lambda的使用大量简化了代码,使得代码简洁、清晰。