邢栋博客

邢栋博客,Action博客,记录工作和生活中的点点滴滴

vim常用操作笔记

普通模式下
w 跳转到下个符号或者单词 b 跳转到上个符号或者单词,对应的大写的WB,跳转的尺度会更大些,比如 I'm 小写会默认是三个,大写会默认为一个

x 删除当前字母
dw 删除下个符号或者单词 db 删除上个符号或者单词
dt+字母  df+字母 删除到某个字母


复制
ctrl+v,然后用鼠标选择要复制的,然后 y,然后p进行粘贴


替换
:s/java/php  替换当前行第一个java为php
:s/java/php/g  替换当前行所有的java为php


:1,$s/java/php 替换第一行开始到最后一行的第一个java为php
:1,$s/java/php/g 替换第一行开始到最后一行的所有 java为php

:%s/java/php 替换每一行的第一个java为php
:%s/java/php/g 替换每一行的所有 java为php



vim = vi + IMproved 
多级撤销
语法加亮和自动补全
支持多种插件
通过网络协议(HTTP/SSH)编辑文件
多文件编辑
Vim可以编辑压缩格式文件(GZIP、ZIP等)

光标移动
h 左移
l   右移
j   下移
k   上移 
^/0  移动到行首/包含缩进空格
$ 移动到行尾


单词和字符传移动
w/W 正向移动到下一个单词开头
b/B 反向移动
e/E 正向移动下一个单词结尾
ge 反向移动词尾

跳转
ctrl+f/F 下一页
ctrl+b/B 上一页
ctrl+d/u  向上或者向上翻半页
gg 跳转到文件首行
<line_number>gg/G  跳转到指定行
G 跳转到文件最后一行
g+ctrl+g/G 查看文件信息/{g}更加详细

缩进 >右  <左
>> 或者 :>  右缩进
m,n> 或者 :m>(n-m+1) m到n行缩进   :3,5> 第3行到5行进行右缩进
m>n 等价于命令 :m,m+n-1>  m行开始共n行缩进一次   :3>3 第3行起包括第3行后3行进行右缩进


删除复制和粘贴

寄存器
类型 含义 表达方式 举例 特点
无名寄存器 默认寄存器 "" "" p=p 会被最后一条覆盖
数字寄存器 "+{0-9}缓存最近10次操作 "0  "{1-9} "0p "1p 0用于复制专用1-9 用于最近9次行删除或者修改记录

有名寄存器 26英文字母命名有名寄存器 "[a-z]/[A-Z] "ayw "A会通过^J追加到" a寄存器中
黑洞寄存器 有去无回 "_ "_dw 只想删除而不想覆盖 无名寄存器


按键操作
d = delete = cut 剪贴
y = yank 约等于 copy 类似于复制
p/P = put 约等于 paste 粘贴到光标后/光标前
u=undo 撤销之前操作
ctrl+r = redo 重做/恢复之前操作

yw 复制当前光标单词
y2w 复制正向两个单词
p/P = put 约等于 paste 粘贴到光标后/光标前
yy类似于dd 复制当前光标整行


组合删除
x/X 删除光标下/前单个字符
dw  删除一个单词,光标必须在词首
d{hjkl} 删除到上下左右一个操作前的字符
d$=D 删除光标到行尾的字符
d^ 删除光标到行首的字符 

dd 删除当前整行
{n}dd  向下删除n行,包括当前行
5dw 删除正向单词五次
3w 正向移动单词三次
D3w 正向删除3w动作
2d3w 正向删除3w动作两次



插入
shift + i/a 插入模式并移动到行首/尾
a/i 光标后/前插入
[n]O/o 行前/后插入n次
[n]+i 插入模式重复n次    // 按键 3i,输入hello,world! ,然后ESC ,会再多出四个此字符串

转换
~  单词字符大小写转换
g~w 单词大小写转换
g~$ 或者 g~~ 整行大小写转换  ,前者需要光标在行首
gU/uw 单词转换成大/小写

查找
F/f{char} 反向/正向查找单个字符
t{char}  查找字符前一个字符
dt{char}/df{space} 删除光标到查找字符间字符
/{char}  命令行查找 ,n向下查找 N向上查找


替换
s/going/rolling/g  当前行所有going替换成rolling
%s/going/rolling/g   %匹配所有范围

shift+r/R 替换模式
r  单个字符替换
cw 修改单个单词
c$/C 类似于d操作 修改光标之后行内容



缓冲区与多文件编辑

缓冲区
缓冲区列表
:files 
:buffers
:ls

缓冲区列表指示状态
标记 含义
a 激活缓冲区,缓冲区被加载且显示
h 隐藏缓冲区,缓冲区被加载但不显示
% 当前缓冲区
# 交换缓冲区
= 只读缓冲区
+ 已经更改缓冲区
- 不可改缓冲区,'modfiable'选项不置位
 
vim *.php 
缓冲区列表操作
:bp 上一个缓冲区
:bn 下一个缓冲区
:bf 到第一个缓冲区
:bl 到最后一个缓冲区
:buffer Number/File_name 指定缓冲区
:ball 编辑所有缓冲区
Ctrl+^/b# 切换到前一个buffer(交换buffer)
:qall! 退出全部缓冲区
:wall! 写入全部缓冲区
:badd 添加一个缓冲区,但不设置为当前缓冲区
:bd 删除缓冲区
:n,m/%bd 删除n到m编号/所有的缓冲区文件
:bufdo{CMD} bufdo set number
:E /:bd 打开文件目录列表/返回到最初的buffer
 
 
多窗口操作(分屏)与标签分组
分屏操作
指令 含义
vim -O/on 水平/垂直分屏 n:数字,分屏的数量,o:open
ctrl+w+c/q 关闭当前窗口/最后一个窗口时退
ctrl+w s 上下分割当前打开的文件
:sp filename 上下分隔,并同时打开一个新的文件
ctrl+w v 左右分隔当前打开的文件
:vsp filename 左右分隔,并打开一个新的文件


移动分屏和尺寸移动
指令 含义
ctrl+w K 向上移动
ctrl+w J 向下移动
ctrl+w L 向右移动
ctrl+w H 向左移动
ctrl+w + 增加高度
ctrl+w - 减少高度
ctrl+w = 让所有屏的高度一致
 


宏操作案例一
文件内容显示如下
1
2


100

需要以下操作

进入普通模式
在第一行写入1
按qa + yyp + (ctrl+a) 
按q退出
按98@a,则会出现1-100的数字   


宏保存
viminfo /vimrc file
保存历史和非空寄存器
vim启动时读取
容易被覆盖



可视化模式
三种子模式
v 激活面向字符的可视模式
V/shift+v 激活面向行的可视模式
ctrl+v 激活面向列块的可视模式

gv 重选上次的高亮选区
o 切换选取

Linux之awk命令

1.awk行处理方式与格式

awk一次处理一行内容
awk对每行可以切片处理

awk '{print $1}' //输出首个单词  uname -a | awk '{print $1}'

命令行格式
awk [options] 'command' file(s)
脚本格式
awk -f awk-script-file  file(s)

command1:pattern {awk操作命令}

操作命令:内置函数: print() printf() getline()
控制指令: if(){...}else{}  while(){...}

awk 内置变量 (1)
$0 表示整个当前行
$1 每行的第一个字段  
$2 每行的第二个字段  

awk内置参数 :分隔符
options : -F field-separator(默认是空格)

例子:
awk -F ':' '{print $1}' /etc/passwd  //打印用户名

awk 内置变量 (2)
NR:每行的记录号
NF:字段数量变量
FILENAME:正在处理的文件名
例子:
awk -F ':' '{print NR,NF,FILENAME}' /etc/passwd 



2.awk内嵌参数应用

awk内置参数应用
1)
awk -F ':' '{if($3>100)print $1,$3}' /etc/passwd
2)
sed -n '/FastCGI/P' error.log | awk '{print $1,$2}' 
等于
cat error.log |awk '/FastCGI/{print $1,$2}'

逻辑判断式
awk逻辑
~,!~ : 匹配正则表达式
==,!=,<,> : 判断逻辑表达式 
例子:
awk -F ':' '$1~/s.*/{print $1}' /etc/passwd  //匹配 s开头的用户名



使用awk扩展格式
awk [options] 'command' file(s)
command2扩展
BEGIN{print "start"}pattern{commands}END{print "end"}


3.awk内嵌程序应用

awk处理过程
案例(-)
统计当前文件夹下的文件/文件夹占用的大小
ls -l | awk 'BEGIN{size=0}{size+=$5}END{print "size is "size/2014/2014"M"}'
案例(二)
统计显示/etc/passwd的账户总人数
awk -F ':' 'BEGIN{count=0}$1!~/^$/{count++}END{print count}' /etc/passwd   //去掉空行

统计uid>100的用户名
awk -F ':' 'BEGIN{count=0}{if($3>100)name[count++]=$1}END{for(i=0;i<count;i++)print i,name[i]}' /etc/passwd

案例(三)
统计netstat -anp 状态下LISTENING和CONNECTED的连接数量
netstat -anp | awk '/CONNECTED|LISTENING/{if($4=="ACC"){sum[$7]++}else{sum[$6]++}}END{for(i in sum)print i,sum[i]}'
php之stream_get_line()和fget()读取文件
php之stream_get_line函数和fget函数读取文件

1.txt内容如下
1111111111111111111112111111111111111111111211111111111111233333333333333

stream_get_line示例
<?php
$file_path = './1.txt';
$fp = fopen($file_path, 'r') or die("open file failure!");
$line = 0;
if ($fp) {
    while ($info = stream_get_line($fp, 8192, "2")) {  //以2为分隔符
        $line++;
    }
    fclose($fp); 
}
echo $line; //结果是4


fgets示例
<?php
$file_path = './1.txt';
$fp = fopen($file_path, 'r') or die("open file failure!");
$line = 0;
if ($fp) {
    while ($info = fgets($fp, 8192)) {
        $line++;
    }
    fclose($fp); 
}
echo $line; //结果是1

总结:
stream_get_line()函数与fgets()几乎相同,只是它允许除标准、标准和\r\n之外的行尾分隔符,并且不返回分隔符本身。
关于栈内存和堆内存
数据结构中的栈和堆:
栈:是一种连续储存的数据结构,具有先进先出的性质。通常的操作有入栈(压栈)、出栈和栈顶元素,就要将之前的所有元素出栈才能完成。类比现实中的箱子一样。
堆:是一种非连续的树形储存结构,每个节点有一个值,整棵树是经过排序的。特点是根节点的值最小(或最大),且根节点的两个子树也是一个堆。常用来实现优先队列,存取随意。

内存中的栈区和堆区:
一般说的内存,指的是计算机的随机储存器(RAM),程序都在这里面运行。
栈内存:由程序自动向操作系统申请分配以及回收,速度快,使用方便,但程序员无法控制。若分配失败,则提示栈溢出错误。注意,const局部变量也存储在栈区内,栈区向地址减小的方向增长。
堆内存:程序员向操作系统申请一块内存,当系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆栈点,然后将该结点从空间结点链表中删除,并将该节点的空间分配给程序。分配的速度较慢,地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则会导致内存泄漏。

关于堆和栈区别的比喻:
堆和栈的区别可以引用一位前辈的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大
golang声明通道struct{}
sign := make(chan struct{}, 3)
sign <- struct{}{}
<-sign
声明通道sign的时候以chan struct{}作为其类型的。其中的类型字面量struct{}有些类似于空接口类型interface{},它代表了既不包含任何字段也不拥有任何方法的空结构体类型。
struct{}类型值的表示方法只有一个,即:struct{}{}。并且,它占用的内存空间是0字节。确切的说,这个值在整个go程序中永远都只会存一份。虽然我们无数次的使用这个值的字面量,但是用到的却都是同一个值。
当我们仅仅把通道当做传递某种简单信号的介质的时候,用struct{}作为其元素类型是再好不过的了。
go语句及其执行规则(goroutine)
go语言不但有着独特的并发编程模型,以及用户级线程goroutine,还拥有强大的用于调度goroutine、对接系统线程的调度器。
这个调度器是go语言运行时系统的重要组成部分,它主要负责统筹调配go并发编程模型中的三个元素,即:G(gotoutine的缩写),P(process的缩写)和M(machine的缩写)。
其中M指代的是系统级线程。而P指的是一种可以承诺若干个G,而且能够使这些G适时地与M进行对接,并得到真正运行的中介。


//demo1:
package main
import (
	"fmt"
	//"time"
)
func main() {
	num := 10
	sign := make(chan struct{}, num)
	for i := 0; i < num; i++ {
		go func() {
			fmt.Println(i)
			sign <- struct{}{}
		}()
	}
	// 办法1。
	//time.Sleep(time.Millisecond * 500)

	// 办法2。
	for j := 0; j < num; j++ {
		<-sign
	}
}

golang让多个goroutine按照既定的顺序运行

//demo1:
package main
import (
	"fmt"
	"sync/atomic"
	"time"
)
func main() {
	var count uint32
	trigger := func(i uint32, fn func()) {
		for {
			if n := atomic.LoadUint32(&count); n == i {
				fn()
				atomic.AddUint32(&count, 1) //count++
				break
			}
			time.Sleep(time.Nanosecond)
		}
	}

	for i := uint32(0); i < 10; i++ {
		go func(i uint32) {
			fn := func() {
				fmt.Println(i)
			}
			trigger(i, fn)
		}(i)
	}
	trigger(10, func() {})
}


关于golang值的内存寻址

go语言哪些值不可以寻址
1.常量的值。 
2.基本类型值的字面量。 
3.算术操作的结果值。
4.对各种字面量的索引表达式和切片表达式的结果值。不过有一个例外,对切片字面量的索引结果值却是可寻址的。
5.对字符串变量的索引表达式和切片表达式的结果值
6.对字典变量的索引表达式的结果值。
7.函数字面量和方法字面量,以及对它们的调用表达式的结果值。
8.结构体字面量的字段值,也就是对结构体字面量的选择表达式的结果值。
9.类型转换表达式的结果值。
10.类型断言表达式的结果值。
11.接收表达式的结果值。

总结:不可变的、临时结果和不安全的
1.不可变的值不可寻址。常量、基本类型的值字面量、字符串变量的值、函数以及方法的字面量都是如此。其实这样规定也有安全性方面的考虑。
2.绝大多数被视为临时结果的值都是不可寻址的。算术操作的结果值属于临时结果,针对值字面量的表达式结果值也属于临时结果。但有一个例外,对切片字面量的索引结果值虽然也属于临时结果,但却是可寻址的。
3.若拿到某值的指针可能会破坏程序的一致性,那么就是不安全的,该值就不可寻址。由于字典的内部机制,对字典的索引结果值的取址操作都是不安全的。另外,获取由字面量或标识符代表的函数或方法的地址显然也是不安全的。

package main

type Named interface {
	// Name 用于获取名字。
	Name() string
}

type Dog struct {
	name string
}

func (dog *Dog) SetName(name string) {
	dog.name = name
}

func (dog Dog) Name() string {
	return dog.name
}

func main() {
	// 示例1。
	const num = 123
	//_ = &num // 常量不可寻址。
	//_ = &(123) // 基本类型值的字面量不可寻址。

	var str = "abc"
	_ = str
	//_ = &(str[0]) // 对字符串变量的索引结果值不可寻址。
	//_ = &(str[0:2]) // 对字符串变量的切片结果值不可寻址。
	str2 := str[0]
	_ = &str2 // 但这样的寻址就是合法的。

	//_ = &(123 + 456) // 算术操作的结果值不可寻址。
	num2 := 456
	_ = num2
	//_ = &(num + num2) // 算术操作的结果值不可寻址。

	//_ = &([3]int{1, 2, 3}[0]) // 对数组字面量的索引结果值不可寻址。
	//_ = &([3]int{1, 2, 3}[0:2]) // 对数组字面量的切片结果值不可寻址。
	_ = &([]int{1, 2, 3}[0]) // 对切片字面量的索引结果值却是可寻址的。
	//_ = &([]int{1, 2, 3}[0:2]) // 对切片字面量的切片结果值不可寻址。


	//_ = &(map[int]string{1: "a"}[0]) // 对字典字面量的索引结果值不可寻址。
	var map1 = map[int]string{1: "a", 2: "b", 3: "c"}
	_ = map1
	//_ = &(map1[2]) // 对字典变量的索引结果值不可寻址。

	//_ = &(func(x, y int) int {
	//	return x + y
	//}) // 字面量代表的函数不可寻址。
	//_ = &(fmt.Sprintf) // 标识符代表的函数不可寻址。
	//_ = &(fmt.Sprintln("abc")) // 对函数的调用结果值不可寻址。

	dog := Dog{"little pig"}
	_ = dog
	//_ = &(dog.Name) // 标识符代表的函数不可寻址。
	//_ = &(dog.Name()) // 对方法的调用结果值不可寻址。

	//_ = &(Dog{"little pig"}.name) // 结构体字面量的字段不可寻址。

	//_ = &(interface{}(dog)) // 类型转换表达式的结果值不可寻址。
	dogI := interface{}(dog)
	_ = dogI
	//_ = &(dogI.(Named)) // 类型断言表达式的结果值不可寻址。
	named := dogI.(Named)
	_ = named
	//_ = &(named.(Dog)) // 类型断言表达式的结果值不可寻址。

	var chan1 = make(chan int, 1)
	chan1 <- 1
	//_ = &(<-chan1) // 接收表达式的结果值不可寻址。

}

golang笔记之Printf函数
package main
import "fmt"
import "os"
type point struct {
	x, y int
}
func main() {
	//Go 为常规 Go 值的格式化设计提供了多种打印方式。例如,这里打印了 point 结构体的一个实例。
	p := point{1, 2}

	fmt.Printf("%v\n", p) // {1 2}
	// 如果值是一个结构体,%+v 的格式化输出内容将包括结构体的字段名。
	fmt.Printf("%+v\n", p) // {x:1 y:2}
	// %#v 形式则输出这个值的 Go 语法表示。例如,值的运行源代码片段。
	fmt.Printf("%#v\n", p) // main.point{x:1, y:2}
	//需要打印值的类型,使用 %T。
	fmt.Printf("%T\n", p) // main.point
	//格式化布尔值是简单的。
	fmt.Printf("%t\n", true)

	//格式化整形数有多种方式,使用 %d进行标准的十进制格式化。
	fmt.Printf("%d\n", 123)
	//这个输出二进制表示形式。
	fmt.Printf("%b\n", 14)
	//这个输出给定整数的对应字符。
	fmt.Printf("%c\n", 33)
	//%x 提供十六进制编码。
	fmt.Printf("%x\n", 456)
	//对于浮点型同样有很多的格式化选项。使用 %f 进行最基本的十进制格式化。
	fmt.Printf("%f\n", 78.9)
	//%e 和 %E 将浮点型格式化为(稍微有一点不同的)科学技科学记数法表示形式。
	fmt.Printf("%e\n", 123400000.0)
	fmt.Printf("%E\n", 123400000.0)

	//使用 %s 进行基本的字符串输出。
	fmt.Printf("%s\n", "\"string\"")
	//像 Go 源代码中那样带有双引号的输出,使用 %q。
	fmt.Printf("%q\n", "\"string\"")
	//和上面的整形数一样,%x 输出使用 base-16 编码的字符串,每个字节使用 2 个字符表示。
	fmt.Printf("%x\n", "hex this")
	//要输出一个指针的值,使用 %p。
	fmt.Printf("%p\n", &p)
	//当输出数字的时候,你将经常想要控制输出结果的宽度和精度,可以使用在 % 后面使用数字来控制输出宽度。默认结果使用右对齐并且通过空格来填充空白部分。
	fmt.Printf("|%6d|%6d|\n", 12, 345)
	//你也可以指定浮点型的输出宽度,同时也可以通过 宽度.精度 的语法来指定输出的精度。
	fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45)
	//要最对齐,使用 - 标志。
	fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45)
	//你也许也想控制字符串输出时的宽度,特别是要确保他们在类表格输出时的对齐。这是基本的右对齐宽度表示。
	fmt.Printf("|%6s|%6s|\n", "foo", "b")
	//要左对齐,和数字一样,使用 - 标志。
	fmt.Printf("|%-6s|%-6s|\n", "foo", "b")
	//到目前为止,我们已经看过 Printf了,它通过 os.Stdout输出格式化的字符串。Sprintf 则格式化并返回一个字符串而不带任何输出。
	s := fmt.Sprintf("a %s", "string")
	fmt.Println(s)
	//你可以使用 Fprintf 来格式化并输出到 io.Writers而不是 os.Stdout。
	fmt.Fprintf(os.Stderr, "an %s\n", "error")
}

优惠券
广告位-淘宝
最新微语