Linux文本处理常用命令

Linux文本处理常用命令:grep、sed、printf、awk、cut、sort

1. grep

按行查找字符,输出包含字符的行
用法

  1. grep ‘key’ test.txt
  2. cat test.txt|grep ‘key’
参数 含义及示例
-n 输出结果加行号
–color=auto 匹配的关键字高亮显示
-A2 输出匹配行的后两行
-B2 输出匹配行的前两行
-v 反向查找,即输出不包含关键字的行
-i 关键字匹配时忽略关键字大小写

例如:

1
grep 'o\{3\}'  //查找两个o,这里需要注意,{}在shell里有特殊意义,因此需要转义。

egrep:

正则表达式分为基本正则表达式和扩展正则表达式,grep只支持基本正则表达式,如果要使用扩展正则表达式,需要使用egrep命令
列如:

1
2
3
egrep '123|1234' //查找123或1234
egrep '1(23|234)5' //查找1235或12345
egrep '1(23)+45' //查找1X45,其中X是一个或一个以上的‘23’字符串

2.sed

sed可以用来做行删除、行新增、行选取、行替换、字符串替换
使用方式:cat test.txt | sed ‘2d’ 或者 sed ‘2d’test.txt

  1. 行删除
    sed ‘2,5d’ //删除第2-5行
    sed ‘3,$d’ //删除第3到最后一行
    sed ‘/^$/d’//删除空行
  2. 行新增
    sed ‘2a abc’ //在第二行下面追加一行“abc”,a代表append
    sed ‘2i abc’ //在第二行上面插入一行 “abc”,i代表insert
    sed ‘2a a\
    b\
    c’  //在第二行下面追加三行 “a”、”b”、”c”,只需要每行结尾加”\”即可。
  3. 行选取
    sed -n ‘7,9p’  //选取第5到7行输出,必须加-n参数,不然效果就是所有行都被输出,而7到9行输出两次。
  4. 行替换
    sed ‘2,5c abc’  //将第2到5行替换为一行字符串”abc”
  5. 字符串替换
    sed ‘s/要被替换的字符串/新的字符串/g’ /可以是#号之类的,在被替换的字符串包含/时,可以考虑别的分隔符。要被替换的字符串可以是
    正则表达式

注意:

1
2
3
4
5
6
7
8
9
10
操作特定区间或规则的行
sed '8,$s/aa/AA/g' test.txt 对第8行到文件末尾的所有行进行搜索替换操作
sed '/^[0-9]/s/aa/AA/g' test.txt 正则表达式表示对所有以数字开头的行,执行s操作

sed的正则中 \(\) 和 \{m,n\} 需要转义
. 表示任意字符
* 表示零个或者多个
\+ 一次或多次  
\? 零次或一次
\| 表示或语法

3. printf

格式化并打印数据
printf ‘%10s %10s %10s %10s %10s \n’ cat test.txt %10s代表这一列的宽度固定为10个字符
%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐)

4. awk

NF :每一行分隔后的列数
NR :行号
FS=”,”:以”,”分割行
cat test.txt |awk ‘NR==1 {printf “%10s %10s %10s %10s %10s \n”,$1,$2,$3,$4,”Total”};NR>1 {printf “%10s %10s %10s %10s %10s \n”,$1,$2,$3,$4,$2+$3+$4}’

  1. 加入条件判断后,awk的格式为: awk ‘条件1 {命令1};条件2{命令2}’
  2. 条件判断有以下逻辑运算:

    1
    2
    3
    4
    5
    6
    >
    <
    >=
    <=
    ==  //注意判断相等要用两个等号
    !=
  3. 可以直接运算行内列的值($1、$2、$3)。

5. 其他

1)cut切割字符

  • 以“,”切割文件并取出第1列
    cat test.txt |cut -d ‘,’ -f 1| sort | uniq -c | sort -rn -k1 > new_test.txt

2)sort排序的时候注意默认是按照字典的方式排序,如果按照数字时则必须加上-n

  • uniq去除重复,只能去除相邻的重复,所以要先排序,后去除重复
命令 用途
grep/egrep 关键字查找
sed 1.行的删除、添加、替换、选取
2.关键字替换
printf 文本格式化输出
awk 1. 将每行按分隔符拆分成列并选取某些列
2. 通过逻辑判断对不同行进行不同的处理
3.对一行中的几列数值进行计算
cat 切割字符
sort 排序

Linux命令

sort

常用参数

  • -n : 依照数值的大小排序。(不加-n参数,默认按照字符ASSII码的排序 会出现如(1,11,2,3..)这样的排序)
  • -k 指定按某一列排序 从1开始。
  • -r: 以相反的顺序来排序。(默认是从小到大,加上-r即从大到小)

  • -t 设定分隔符,使用指定的分隔符代替非空格到空格的转换
  • -b 忽略每行前面开始出的空格字符。
  • -c 检查文件是否已经按照顺序排序。
  • -d 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
  • -f 排序时,将小写字母视为大写字母。
  • -i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
  • -m 将几个排序好的文件进行合并。
  • -M 将前面3个字母依照月份的缩写进行排序。
  • -o<输出文件> 将排序后的结果存入指定的文件。
  • +<起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
    sort -n -k 2 -t’-‘ test.txt
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //原来的内容
    [root@h2 ~]# cat test.txt
    2018-12-01
    2013-01-08
    2015-10-24
    2016-04-25

    [root@h2 ~]# sort -nk2 -t'-' test.txt
    2013-01-08
    2016-04-25
    2015-10-24
    2018-12-01

head用于显示文件的开头的内容。在默认情况下,head命令显示文件的头10行内容。

  • -n<数字> –lines=[-]K :指定显示头部内容的行数;如果附加”-“参数,则除了每个文件的最后K 行外显示
    剩余全部内容
    
  • -v:总是显示文件名的头信息;
  • -q:不显示文件名的头信息。
  • -c, –bytes=[-]K 显示每个文件的前K 字节内容

uniq

只过滤相邻的重复行。

  • -c, –count 在每行前加上表示相应行目出现次数的前缀编号

find

  • find base_path 列出当前目录和子目录下的所有文件和文件夹
  • find path -name ‘*txt’ 根据文件名或者正则表达式匹配搜索
  • find path -iname ‘*txt’ 同上,忽略大小写
  • find path ! -name ‘*txt’ 对上面的搜索结果取反
  • find path -type d 根据文件类型搜索,d文件夹,f普通文件,etc
  • find path -type f -size +2k 根据文件大小搜索,+2k大于2k的文件,-2k小于2k的文件,2k等你2k的文件
  • find path -type f -name ‘*txt’ -delete 删除匹配到的文件
  • find path -mtime -2 查找文件更新日时在距现在时刻二天以内的文件
  • find path -mtime +2 查找文件更新日时在距现在时刻二天以上的文件
  • find path -mtime 2 查找文件更新日时在距现在时刻一天以上二天以内的文件
  • find path -mmin -2 查找文件更新日时在距现在时刻二分以内的文件
  • find path -mmin +2 查找文件更新日时在距现在时刻二分以上的文件
  • find path -mmin 2 查找文件更新日时在距现在时刻一分以上二分以内的文件
  • find path -perm 664 查找权限为664的文件或目录(需完全符合)
  • find path -empty 查找空文件或空目录
  • find path -empty -type f -print -delete查找空文件并删除
  • find path -size -10c 查找文件size小于10个字节的文件或目录
  • find path -size 10c 查找文件size等于10个字节的文件或目录
  • find path -size +10c 查找文件size大于10个字节的文件或目录
  • find path -size -10k 查找文件size小于10k的文件或目录
  • find path -size -10M 查找文件size小于10M的文件或目录
  • find path -size -10G 查找文件size小于10G的文件或目录

Git创建本地分支并关联远程分支

创建本地分支

  • git branch 分支名

切换到本地分支

  • git checkout 分支名

创建本地分支并切换到该分支

  • git checkout -b 分支名

提交本地分支到远程仓库

  • git push origin 本地分支名

将新建的本地分支与远程分支关联

-git branch –set-upstream-to=origin/远程分支名 本地分支名
使用git branch –set-upstream 本地分支名 origin/远程分支名 命令报如下错误
fatal: the ‘–set-upstream’ option is no longer supported. Please use ‘–track’ or ‘–set-upstream-to’ instead.

Git常用命令

  • git init
    • 在本地当前目录初始化一个git仓库
  • git clone

  • git status

  • git log

  • git add

  • git diff

  • git commit

  • git reset

  • git revert

  • git rm

  • git clean

  • git mv

  • git stash

  • git branch

  • git checkout

  • git merge

  • git tag

  • git remote

  • git fetch

  • git pull

  • git rebase

  • git push

设计模式

设计模式的分类

设计模式分为三大类:

  • 创建型模式,共五种:
    • 工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式
  • 结构型模式,共七种:
    • 适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式
  • 行为型模式,共十一种:
    • 策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,
      中介者模式,解释器模式

设计模式的六大原则

1、单一职责原则

  • 不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。

2、里氏替换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科

历史替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。

3、依赖倒转原则(Dependence Inversion Principle)

  • 这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

4、接口隔离原则(Interface Segregation Principle)

  • 每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

5、迪米特法则(最少知道原则)(Demeter Principle)

  • 一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

  • 最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。

6、合成复用原则(Composite Reuse Principle)

  • 原则是尽量首先使用合成/聚合的方式,而不是使用继承。

【Java并发】Java多线程Future的使用

Future模式简述

  • 在传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理。
  • Future模式下,调用方式改为异步。
  • Future模式的核心在于:充分利用主函数中的等待时间,利用等待时间处理其他任务,充分利用计算资源
    示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.concurrent.Callable;

public class ManipulationDataTask implements Callable<String> {
private String data;

public ManipulationDataTask(String data) {
this.data = data;
}

@Override
public String call() throws Exception {
String data1 = data.toUpperCase();
System.out.println(Thread.currentThread().getName() + "业务处理线程处理中...");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "业务处理线程处理完成,处理好的数据为" + data1);
return data1;
}
}
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
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class MainTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {

FutureTask<String> future1 = new FutureTask<String>(new ManipulationDataTask("abc"));
FutureTask<String> future2 = new FutureTask<String>(new ManipulationDataTask("def"));
FutureTask<String> future3 = new FutureTask<String>(new ManipulationDataTask("ghi"));
ManipulationDataTask manipulationDataTask = new ManipulationDataTask("jkl");
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(future1);
executor.submit(future2);
executor.submit(future3);
Future<String> future4 =executor.submit(manipulationDataTask);
System.out.println("请求完毕!");
try {
System.out.println("主线程先去做点别的事");
Thread.sleep(5000);
System.out.println("主线程的事情做完了");
} catch (InterruptedException e) {

}
System.out.println("主线程开始获取子任务处理完的结果");
System.out.println("数据处理完成:" + future1.get());
System.out.println("数据处理完成:" + future2.get());
System.out.println("数据处理完成:" + future3.get());
System.out.println("数据处理完成:" + future4.get());
executor.shutdown();
}
}

程序运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
请求完毕!
主线程先去做点别的事
pool-1-thread-1业务处理线程处理中...
pool-1-thread-2业务处理线程处理中...
pool-1-thread-3业务处理线程处理中...
pool-1-thread-1业务处理线程处理完成,处理好的数据为ABC
pool-1-thread-1业务处理线程处理中...
pool-1-thread-2业务处理线程处理完成,处理好的数据为DEF
pool-1-thread-3业务处理线程处理完成,处理好的数据为GHI
pool-1-thread-1业务处理线程处理完成,处理好的数据为JKL
主线程的事情做完了
主线程开始获取子任务处理完的结果
数据处理完成:ABC
数据处理完成:DEF
数据处理完成:GHI
数据处理完成:JKL

java关键字transient,volatile

被transient关键字修饰的变量不会被序列化

被volatile关键字修饰的变量,每次被线程访问时,都会强制从共享内存中重读改变量的值,但是不具备原子性

被volatile关键字修饰的变量的,具有以下两点特性:

  1. 保证了不同线程对该变量操作的内存可见性,不保证原子性。
  2. 禁止指令重排序

在java的内存模型中,JMM规定对于多个线程共享变量都存在主存中的,每个线程包含自己的工作内存,工作内存保存了主内存共享的变量,
其中一个线程要操作这些共享变量,只能通过操作工作内存中的副本来实现,操作完毕之后再同步会主内存中。在其他线程未将共享变量同步
会自己的工作内存之前,共享变量的改变对其不可见的。也就是说其他线程的工作内存中的变量已经过时了。

volatile是通过内存屏障和禁止指令重排序来保证内存可见性的,一个线程对volatile变量的修改,能即刻被其他线程所见,
但是不保证原子性。

使用volatile提供理想的线程安全,需要满足以下两个条件:

  1. 对变量的写操作不依赖于当前值
  2. 该变量没有包含在具有其他变量的不变式中

volatile变量不能用来做线程安全的计数器

volatile的适用场景

1. 状态标志

注意:这种状态标记通常只有一种状态转换如果需要状态的来回转换,可以使用原子变量。

2. 一次性安全发布

3. 独立观察

定期“发布”观察结果供程序内部使用

4. “volatile bean”模式

5. 开销较低“读-写锁”策略


  • 状态位
  • 一个线程写,多个线程读的场景

SpringAOP原理

AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。

AOP使用场景

  • 权限
  • 缓存
  • 内容传递
  • 错误处理
  • 懒加载
  • 调试
  • 记录跟踪 优化 校准
  • 持久化
  • 资源池
  • 同步
  • 事务

Github 提交代码 Emoji

An emoji guide for your commit messages: gitmoji

Code Emoji 描述
:art: :art: 改进代码的结构/格式
:zap: :zap: 提高性能
:fire: :fire: 删除代码或文件
:bug: :bug: 修复bug
:ambulance: :ambulance: 关键修补程序
:sparkles: :sparkles: 引入新功能
:memo: :memo: 写文档
:rocket: :rocket: 部署项目
:lipstick: :lipstick: 更新UI和样式文件
:tada: :tada: 初始提交
:white_check_mark: :white_check_mark: 添加测试
:lock: :lock: 解决安全问题
:apple: :apple: 修改 macOS 下的一些问题
:penguin: :penguin: 修改 Linux 下的一些问题
:checkered_flag: :checkered_flag: 修改 Windows 下的一些问题
:robot: :robot: 修改 Android 下的一些问题
:green_apple: :green_apple: 修改 IOS 下的一些问题
:bookmark: :bookmark: 发布版本标签
:rotating_light: :rotating_light: 移除 linter 警告
:construction: :construction: 工作正在进行中
:green_heart: :green_heart: 修复CI构建
:arrow_down: :arrow_down: 降级依赖
:arrow_up: :arrow_up: 更新依赖
:construction_worker: :construction_worker: 添加CI构建系统
:chart_with_upwards_trend: :chart_with_upwards_trend: 添加分析或跟踪代码
:hammer: :hammer: 重构代码
:heavy_minus_sign: :heavy_minus_sign: 删除依赖关系
:whale: :whale: 关于Docker的工作
:heavy_plus_sign: :heavy_plus_sign: 添加依赖关系
:wrench: :wrench: 更改配置文件
:globe_with_meridians: :globe_with_meridians: 国际化和本地化
:pencil2: :pencil2: 修正打字错误
:hankey: :hankey: 编写不好的代码,需要改进
:rewind: :rewind: 还原更改
:twisted_rightwards_arrows: :twisted_rightwards_arrows: 合并分支
:package: :package: 更新已编译的文件或包
:alien: :alien: 由于外部API更改而更新代码
:truck: :truck: 移动或重命名文件
:page_facing_up: :page_facing_up: 添加或更新许可证
:boom: :boom: 引入爆炸改变
:bento: :bento: 添加或更新资源
:ok_hand: :ok_hand: 由于代码审查更改而更新代码
:wheelchair: :wheelchair: 改善无障碍
:bulb: :bulb: 文档化源代码
:beers: :beers: 沉迷写代码
:speech_balloon: :speech_balloon: 更新文本和常量
:card_file_box: :card_file_box: 执行数据库相关更改