add shell
parent
829bc17bcb
commit
1fcdef61da
|
@ -0,0 +1,88 @@
|
|||
在写项目相关的解释文档或者说明文档或者需求文档的时候,经常需要列出项目代码的树状结构。tree命令就能很好的满足我们这个小小的需求
|
||||
|
||||
linux与mac中的tree都不是自带的,需要自行安装。如果不会安装,请自行google在linux或者mac中怎样安装软件即可。。。
|
||||
|
||||
## 1.最简单的方式
|
||||
最简单的使用方式就是直接输入`tree`命令了 :
|
||||
|
||||
```
|
||||
$ tree
|
||||
.
|
||||
├── get_user_order.sh
|
||||
├── mr.py
|
||||
├── test
|
||||
│ ├── mr.py
|
||||
│ ├── subtest
|
||||
│ │ └── a.txt
|
||||
│ └── zzz.sh
|
||||
├── zzzfile
|
||||
└── zzz.sh
|
||||
|
||||
2 directories, 7 files
|
||||
```
|
||||
|
||||
会把当前目录中所有的文件夹以及文件都遍历出来。当然,大部分情况下我们还会有别的需求,请接着往下看。
|
||||
|
||||
## 2.-L选项
|
||||
-L选项是我实际中使用最多的参数。因为很多情况下可能文件夹的层数非常多,我不希望看到后面所有的文件夹,这个时候用-L选项即可搞定。
|
||||
|
||||
```
|
||||
$ tree -L 1
|
||||
.
|
||||
├── get_user_order.sh
|
||||
├── mr.py
|
||||
├── test
|
||||
├── zzzfile
|
||||
└── zzz.sh
|
||||
|
||||
1 directory, 4 files
|
||||
```
|
||||
|
||||
-L后面跟一个数字,比如现在指定为1,表示最多看当前目录下一层目录。
|
||||
|
||||
## 3.-d选项
|
||||
|
||||
```
|
||||
$ tree -d
|
||||
.
|
||||
└── test
|
||||
└── subtest
|
||||
|
||||
2 directories
|
||||
```
|
||||
|
||||
只看文件夹,不解释。
|
||||
|
||||
## 4.-I选项
|
||||
实际中还经常想忽略某些内容,这个时候-I就派上了用场。
|
||||
|
||||
```
|
||||
$ tree -I zzzfile
|
||||
.
|
||||
├── get_user_order.sh
|
||||
├── mr.py
|
||||
├── test
|
||||
│ ├── mr.py
|
||||
│ ├── subtest
|
||||
│ │ └── a.txt
|
||||
│ └── zzz.sh
|
||||
└── zzz.sh
|
||||
|
||||
2 directories, 6 files
|
||||
```
|
||||
|
||||
如果要忽略多个,也很简单
|
||||
|
||||
```
|
||||
$ tree -I "zzzfile|a.txt"
|
||||
.
|
||||
├── get_user_order.sh
|
||||
├── mr.py
|
||||
├── test
|
||||
│ ├── mr.py
|
||||
│ ├── subtest
|
||||
│ └── zzz.sh
|
||||
└── zzz.sh
|
||||
|
||||
2 directories, 5 files
|
||||
```
|
|
@ -0,0 +1,97 @@
|
|||
代码中免不了要进行各种数据计算。抛开科学计算不提,普通的计算占地,百分比,同比,环比等需求就很常见。linux shell中进行数字计算,主要有如下几种方式:
|
||||
|
||||
## 1.bc
|
||||
bc是比较常用的linux计算工具了,而且支持浮点运算:
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ a=`echo 1+1 | bc`
|
||||
[webopa@namenode-backup expensive_user]$ echo $a
|
||||
2
|
||||
```
|
||||
|
||||
但是浮点数运算的精度问题,暂时还没明白什么情况:
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ b=`echo "1.2*1.2" | bc`
|
||||
[webopa@namenode-backup expensive_user]$ echo $b
|
||||
1.4
|
||||
[webopa@namenode-backup expensive_user]$ c=`echo "5.0/3.0" | bc`
|
||||
[webopa@namenode-backup expensive_user]$ echo $c
|
||||
1
|
||||
[webopa@namenode-backup expensive_user]$ d=`echo "scale=2;5.0/3.0" | bc`
|
||||
[webopa@namenode-backup expensive_user]$ echo $d
|
||||
1.66
|
||||
[webopa@namenode-backup expensive_user]$ e=`echo "scale=2;5.0/6.0" | bc`
|
||||
[webopa@namenode-backup expensive_user]$ echo $e
|
||||
.83
|
||||
```
|
||||
|
||||
尤其最后一个,这到底什么鬼,小数点前的那个0跑哪里去了。。。
|
||||
|
||||
## 2.expr
|
||||
不支持浮点数计算。这又是个大坑.而且要注意数字与运算符中的空格
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ a=`expr 1+1`
|
||||
[webopa@namenode-backup expensive_user]$ echo $a
|
||||
1+1
|
||||
[webopa@namenode-backup expensive_user]$ a=`expr 1 + 1`
|
||||
[webopa@namenode-backup expensive_user]$ echo $a
|
||||
2
|
||||
[webopa@namenode-backup expensive_user]$ b=`expr 10 / 2`
|
||||
[webopa@namenode-backup expensive_user]$ echo $b
|
||||
5
|
||||
```
|
||||
|
||||
## 3.$(())
|
||||
同expr,不支持浮点数运算
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ a=$((1+1))
|
||||
[webopa@namenode-backup expensive_user]$ echo $a
|
||||
2
|
||||
[webopa@namenode-backup expensive_user]$ b=$((1 + 3 ))
|
||||
[webopa@namenode-backup expensive_user]$ echo $b
|
||||
4
|
||||
```
|
||||
|
||||
## 4.let
|
||||
不支持浮点数运算,而且不支持直接输出,只能赋值
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ let a=1+1
|
||||
[webopa@namenode-backup expensive_user]$ echo $a
|
||||
2
|
||||
[webopa@namenode-backup expensive_user]$ let b=50/5
|
||||
[webopa@namenode-backup expensive_user]$ echo $b
|
||||
10
|
||||
[webopa@namenode-backup expensive_user]$ let c=1.2*2
|
||||
-bash: let: c=1.2*2: syntax error: invalid arithmetic operator (error token is ".2*2")
|
||||
```
|
||||
|
||||
## 5.awk
|
||||
普通的运算:
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ a=`echo | awk '{print 1.0/2.0}'`
|
||||
[webopa@namenode-backup expensive_user]$ echo $a
|
||||
0.5
|
||||
```
|
||||
|
||||
控制精度:
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ b=`echo | awk '{printf("%.2f",1.0/2.0)}'`
|
||||
[webopa@namenode-backup expensive_user]$ echo $b
|
||||
0.50
|
||||
```
|
||||
|
||||
传递参数:
|
||||
|
||||
```
|
||||
[webopa@namenode-backup expensive_user]$ c=`echo | awk -v a=1 -v b=3 '{printf("%.4f",a/b)}'`
|
||||
[webopa@namenode-backup expensive_user]$ echo $c
|
||||
0.3333
|
||||
```
|
||||
|
||||
综合来看,还是awk最靠谱,其他的方式都有这样那样的问题。所以我平时一般都用awk来搞数学计算。
|
|
@ -0,0 +1,65 @@
|
|||
## VIRT:virtual memory usage 虚拟内存
|
||||
1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等
|
||||
2、假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量
|
||||
|
||||
## RES:resident memory usage 常驻内存
|
||||
1、进程当前使用的内存大小,但不包括swap out
|
||||
2、包含其他进程的共享
|
||||
3、如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反
|
||||
4、关于库占用内存的情况,它只统计加载的库文件所占内存大小
|
||||
|
||||
## SHR:shared memory 共享内存
|
||||
1、除了自身进程的共享内存,也包括其他进程的共享内存
|
||||
2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小
|
||||
3、计算某个进程所占的物理内存大小公式:RES – SHR
|
||||
4、swap out后,它将会降下来
|
||||
|
||||
## DATA
|
||||
1、数据占用的内存。如果top没有显示,按f键可以显示出来。
|
||||
2、真正的该程序要求的数据空间,是真正在运行中要使用的。
|
||||
|
||||
## top 运行中可以通过 top 的内部命令对进程的显示方式进行控制。内部命令如下:
|
||||
s – 改变画面更新频率
|
||||
l – 关闭或开启第一部分第一行 top 信息的表示
|
||||
t – 关闭或开启第一部分第二行 Tasks 和第三行 Cpus 信息的表示
|
||||
m – 关闭或开启第一部分第四行 Mem 和 第五行 Swap 信息的表示
|
||||
N – 以 PID 的大小的顺序排列表示进程列表
|
||||
P – 以 CPU 占用率大小的顺序排列进程列表
|
||||
M – 以内存占用率大小的顺序排列进程列表
|
||||
h – 显示帮助
|
||||
n – 设置在进程列表所显示进程的数量
|
||||
q – 退出 top
|
||||
s – 改变画面更新周期
|
||||
|
||||
## 序号 列名 含义
|
||||
a PID 进程id
|
||||
b PPID 父进程id
|
||||
c RUSER Real user name
|
||||
d UID 进程所有者的用户id
|
||||
e USER 进程所有者的用户名
|
||||
f GROUP 进程所有者的组名
|
||||
g TTY 启动进程的终端名。不是从终端启动的进程则显示为 ?
|
||||
h PR 优先级
|
||||
i NI nice值。负值表示高优先级,正值表示低优先级
|
||||
j P 最后使用的CPU,仅在多CPU环境下有意义
|
||||
k %CPU 上次更新到现在的CPU时间占用百分比
|
||||
l TIME 进程使用的CPU时间总计,单位秒
|
||||
m TIME+ 进程使用的CPU时间总计,单位1/100秒
|
||||
n %MEM 进程使用的物理内存百分比
|
||||
o VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
|
||||
p SWAP 进程使用的虚拟内存中,被换出的大小,单位kb。
|
||||
q RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
|
||||
r CODE 可执行代码占用的物理内存大小,单位kb
|
||||
s DATA 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kb
|
||||
t SHR 共享内存大小,单位kb
|
||||
u nFLT 页面错误次数
|
||||
v nDRT 最后一次写入到现在,被修改过的页面数。
|
||||
w S 进程状态。(D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程)
|
||||
x COMMAND 命令名/命令行
|
||||
y WCHAN 若该进程在睡眠,则显示睡眠中的系统函数名
|
||||
z Flags 任务标志,参考 sched.h
|
||||
|
||||
默认情况下仅显示比较重要的 PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME+、COMMAND 列。可以通过下面的快捷键来更改显示内容。
|
||||
通过 f 键可以选择显示的内容。按 f 键之后会显示列的列表,按 a-z 即可显示或隐藏对应的列,最后按回车键确定。
|
||||
按 o 键可以改变列的显示顺序。按小写的 a-z 可以将相应的列向右移动,而大写的 A-Z 可以将相应的列向左移动。最后按回车键确定。
|
||||
按大写的 F 或 O 键,然后按 a-z 可以将进程按照相应的列进行排序。而大写的 R 键可以将当前的排序倒转。
|
|
@ -0,0 +1,14 @@
|
|||
下来搜狐实验室一些新闻语料做分析,结果打开发现其他标签都正常,就$<content>$标签内容不正常,全是乱码。因此估计十有八九是编码问题。上网找了下linux里怎么解决中文乱码的问题。
|
||||
|
||||
其实挺简单,用iconv命令就可以轻松搞定。linux里默认的字符集编码方式是utf-8,而下载的内容的编码格式应该是gbk,所以用如下命令:
|
||||
|
||||
```
|
||||
cat news.allsites.1120806.txt | iconv -f gbk -t utf-8 -c | grep "<content>" >zzz
|
||||
```
|
||||
|
||||
iconv命令就是将制定文件从一种编码方式换到另外一种一种编码。
|
||||
-f,--from-code ,表示文本的原始编码方式
|
||||
-t, --to-code 表示文本的输出编码方式
|
||||
-c 表示在输出中忽略无效字符
|
||||
|
||||
最后再配合grep命令,就将文本中的正文内容提取出来
|
|
@ -0,0 +1,9 @@
|
|||
新建文件或者保存文件时候,很容易输入乱码字符,导致最后生成的文件名中有各种奇怪符号。当文件名包含这些符号的时候,我们就无法通过键盘输入文件名,所以在终端下就不能直接利用rm,mv等命令管理文件了。
|
||||
|
||||
但是我们知道每个文件都有一个i节点号,我们可以考虑通过i节点号来管理文件。首先,我们要取得文件的i节点号。通过简单的ls -i 命令就可以得到文件的i节点号。然后,使用find命令将文件名传递给rm命令。
|
||||
|
||||
删除节点为xxx的乱码文件夹可以使用如下命令(代码经过测试,表示没有问题)
|
||||
|
||||
find ./ -inum xxx -print -exec rm {} -rf \;
|
||||
|
||||
注意\;前面的空格不能少,少了就会报错。
|
|
@ -0,0 +1,22 @@
|
|||
Linux 守护进程概述
|
||||
Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。
|
||||
|
||||
守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。
|
||||
|
||||
一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。
|
||||
|
||||
|
||||
工作原理
|
||||
Linux 守护进程的工作模式是服务器/客户机(Server/Client),服务器在一个特定的端口上监听(Listen)等待客户连接,连接成功后服务器和客户端通过端口进行数据通信。守护进程的工作就是打开一个端口,并且监听(Listen)等待客户连接。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听其他的服务请求。
|
||||
|
||||
工作模式
|
||||
Linux 守护进程有两种工作模式:stand-alone模式和xinetd模式。
|
||||
1.stand-alone模式
|
||||
独立运行的守护进程由init负责管理,所有独立运行守护进程的脚本在/etc/rc.d/init.d/目录下。独立运行的守护进程工作方式称作stand-alone,是Unix传统的C/S模式的访问模式。服务器监听(Listen)在一个特点的端口上等待客户端的联机。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听。工作在stand-alone模式下的网络服务有route、gated、web服务器等。在Linux系统中通过stand-alone工作模式启动的服务由/etc/rc.d/下面对应的运行级别当中的符号链接启动。
|
||||
|
||||
2.xinetd模式
|
||||
从守护进程的概念可以看出,对于系统所要求的每一种服务,都必须运行一个监听某个端口连接所发生的守护进程,这意味着资源浪费。为了解决这个问题,Linux引进了"网络守护进程服务程序"的概念。Redhat Linux使用的网络守护进程是xinted(eXtended InterNET Daemon)。和stand-alone模式相比xinetd模式也称 InternetSuper-Server(超级服务器)。xinetd能够同时监听多个指定的端口,在接受用户请求时,他能够根据用户请求的端口不同,启动不同的网络服务进程来处理这些用户请求。可以把xinetd看做一个管理启动服务的管理服务器,它决定把一个客户请求交给那个程序处理,然后启动相应的守护进程。
|
||||
|
||||
和stand-alone工作模式相比,系统不必为每一个网络服务进程监听其服务端口,运行xinetd守护进程就可以同时监听所有服务端口,这样就降低了系统开销,保护系统资源。但是对于访问量大、经常出现并发访问时,xinetd想要频繁启动对应的网络服务进程,反而会导致系统性能下降。一般来说系统一些负载高的服务,比如Apache、sendmail等服务是单独启动的。而其他服务类型都可以使用xinetd超级服务器管理。
|
||||
|
||||
查看系统为Linux服务提供那种模式方法在Linux命令行可以使用pstree命令可以看到两种不同方式启动的网络服务。
|
|
@ -0,0 +1,12 @@
|
|||
统计文件夹下的文件个数(当前目录与子目录)
|
||||
|
||||
```
|
||||
find ./ -type f | wc -l
|
||||
ls -lR | grep "^-" | wc -l
|
||||
```
|
||||
|
||||
如果只是查找当前文件夹不递归
|
||||
|
||||
```
|
||||
find . -maxdepth 1 -type d | wc -l
|
||||
```
|
|
@ -0,0 +1,118 @@
|
|||
## 求字符串长度:
|
||||
```
|
||||
$ x="a:b:c:"
|
||||
方法一:
|
||||
$ echo ${#x}
|
||||
6
|
||||
```
|
||||
|
||||
```
|
||||
方法二:用expr命令
|
||||
$ expr length $x
|
||||
6
|
||||
```
|
||||
|
||||
PS:expr属于外部命令,一般来说外部命令比内部命令要慢很多
|
||||
|
||||
```
|
||||
$ time for i in $(seq 1 10000);do len=${#x};done
|
||||
|
||||
real 0m0.087s
|
||||
user 0m0.081s
|
||||
sys 0m0.001s
|
||||
```
|
||||
|
||||
```
|
||||
$ time for i in $(seq 1 10000);do len=$(expr length $x);done
|
||||
|
||||
real 0m13.313s
|
||||
user 0m2.578s
|
||||
sys 0m9.982s
|
||||
```
|
||||
|
||||
|
||||
## 字符串拼接
|
||||
```
|
||||
$ echo $x"ddd"
|
||||
a:b:c:ddd
|
||||
```
|
||||
|
||||
|
||||
## 查找字符串位置
|
||||
|
||||
返回的索引是从1开始, 失败则返回0
|
||||
```
|
||||
$ expr index $x "a"
|
||||
1
|
||||
$ expr index $x "c"
|
||||
5
|
||||
expr index $x "d"
|
||||
0
|
||||
```
|
||||
|
||||
|
||||
得到子字符串
|
||||
```
|
||||
方法一:${x:pos:length},本人一般用这种方式,嘻嘻
|
||||
$ echo ${x:0:4}
|
||||
a:b:
|
||||
$ echo ${x:0}
|
||||
a:b:c:
|
||||
$ echo ${x:2}
|
||||
b:c:
|
||||
|
||||
方法二: expr substr <string> startpos length
|
||||
$ expr substr "$x" 1 2
|
||||
a:
|
||||
$ expr substr "$x" 1 10
|
||||
a:b:c:
|
||||
```
|
||||
|
||||
字符串替换
|
||||
|
||||
非贪婪模式
|
||||
```
|
||||
$ echo ${x/a/b}
|
||||
b:b:c:
|
||||
```
|
||||
|
||||
贪婪模式
|
||||
```
|
||||
$ xx="aaaaaa"
|
||||
$ echo ${xx//a/b}
|
||||
bbbbbb
|
||||
```
|
||||
|
||||
## 处理字符串的头尾
|
||||
```
|
||||
$ zzz="this is a test"
|
||||
```
|
||||
|
||||
\# 表示去掉头,一个为非贪婪模式,两个为贪婪模式
|
||||
```
|
||||
$ echo ${zzz#t}
|
||||
his is a test
|
||||
$ echo ${zzz#t*h}
|
||||
is is a test
|
||||
$ echo ${zzz##t*s}
|
||||
t
|
||||
```
|
||||
|
||||
%表示去掉尾,一个为非贪婪模式,两个为贪婪模式
|
||||
```
|
||||
$ echo ${zzz%t}
|
||||
this is a tes
|
||||
$ echo ${zzz%s*t}
|
||||
this is a te
|
||||
$ echo ${zzz%e*t}
|
||||
this is a t
|
||||
$ echo ${zzz%%s*t}
|
||||
thi
|
||||
```
|
||||
|
||||
去掉字符串最后一个字符
|
||||
```
|
||||
$ x='a:b:c:'
|
||||
$ echo ${x%?}
|
||||
a:b:c
|
||||
```
|
|
@ -0,0 +1,26 @@
|
|||
有时候需要将sql查询封装在shell脚本中,然后将查询结果导出存入文本后续再做进一步处理。对于这种常见需求,特意做了个实例,代码已经通过测试,同学们可以大胆使用。
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
host=xxx
|
||||
user=xxx
|
||||
password=xxx
|
||||
port=xxx
|
||||
dbname=xxx
|
||||
|
||||
sql_conn_str="-h${host} -P${port} -u${user} -p${password} $dbname"
|
||||
|
||||
function select_from_mysql()
|
||||
{
|
||||
sql="xxxxxx"
|
||||
echo "$sql" | mysql -s $sql_conn_str >resultfile
|
||||
}
|
||||
|
||||
select_from_mysql
|
||||
```
|
||||
|
||||
上面的代码就可以满足我们的需求。注意的几个小点:
|
||||
1.实际使用时候,将数据库各配置项,以及具体的sql查询语句替换成实际配置项即可。
|
||||
2.mysql -s选项表示查询输出的结果不带字段名称,如果不加-s选项会输出字段名称。
|
||||
3.将resultfile换成你最终结果文件存储的地址。
|
|
@ -0,0 +1,26 @@
|
|||
做性能测试的时候,经常需要得到程序运行时间。
|
||||
|
||||
写了个简答的shell脚本,供同学们参考。
|
||||
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
function handle()
|
||||
{
|
||||
start=$(date +%s%N)
|
||||
start_ms=${start:0:16}
|
||||
awk '{a[$1]++} END{print length(a)}' breakfast_all receptions_all cheap_all
|
||||
end=$(date +%s%N)
|
||||
end_ms=${end:0:16}
|
||||
echo "cost time is:"
|
||||
echo "scale=6;($end_ms - $start_ms)/1000000" | bc
|
||||
}
|
||||
|
||||
handle
|
||||
|
||||
```
|
||||
|
||||
代码思路比较清晰 %s是精确到秒,%N是纳秒,取字符串前16位,得到的是秒后小数点六位。再除以1000000,最终的结果为以s为单位,精确到小数点后6位。
|
||||
|
||||
需要不同的精度,调整字符串截取的位数即可。
|
|
@ -0,0 +1,39 @@
|
|||
## 1.问题描述
|
||||
新安装的ubuntu18系统,自己下载的软件包安装好以后,无法将启动图标固定在dock栏上,导致每次启动都要去软件安装的目录中执行对应的启动脚本,非常不方便。为了解决上述问题,可以采用如下解决方案。
|
||||
|
||||
## 2.解决办法
|
||||
以pycharm为例
|
||||
|
||||
在`~/.local/share/applications`目录中,新建pycharm.desktop文件
|
||||
|
||||
```
|
||||
[Desktop Entry]
|
||||
|
||||
Encoding=UTF-8
|
||||
|
||||
Name=PyCharm
|
||||
|
||||
Exec=.../soft/pycharm-community-2020.1.1/bin/pycharm.sh
|
||||
Icon=.../soft/pycharm-community-2020.1.1/bin/pycharm.svg
|
||||
|
||||
Terminal=false
|
||||
|
||||
Type=Application
|
||||
|
||||
Categories=Development
|
||||
```
|
||||
|
||||
对应的Exec是pycharm的启动脚本位置,Icon是对应的图标位置。
|
||||
|
||||
添加完上述文件以后,点击左下角的“显示应用程序”,然后找到pycharm的图标,右击,选择添加到收藏夹即可。
|
||||
|
||||
## 3. 消除侧边栏出现两个图标
|
||||
启动时,侧边栏会出现两个图标,体验还是很差的。
|
||||
具体的解决方案:
|
||||
在terminate中执行`xprop |grep WM_CLASS`,此时鼠标会变成一个十字的准星。此时点击已经打开的pycharm界面,会出现如下内容:
|
||||
|
||||
`WM_CLASS(STRING) = "jetbrains-pycharm-ce", "jetbrains-pycharm-ce"`
|
||||
|
||||
然后在pycharm.desktop后面添加一行:
|
||||
`StartupWMClass=jetbrains-pycharm-ce`
|
||||
即可。
|
|
@ -0,0 +1,70 @@
|
|||
批量重命名文件名是常见的需求。例如我们这有三个文件都是以.txt结尾,现在我们想重命名为.csv文件。以下给同学们介绍如下两种方式。
|
||||
|
||||
## 1.使用mv命令
|
||||
话不多少,直接上代码
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
for file in `ls`
|
||||
do
|
||||
newfile=`echo $file | sed 's/\.txt/\.csv/'`
|
||||
mv $file $newfile
|
||||
done
|
||||
```
|
||||
|
||||
mv的方式如上。如果不是修改后缀而是其他方式,修改后面sed的正则表达方式即可。
|
||||
|
||||
## 2.使用rename命令
|
||||
|
||||
```
|
||||
rename .txt .csv *
|
||||
```
|
||||
|
||||
rename 命令可能实际中用得不如mv多。rename最大的好处就是可以同时处理多个文件。来看看rename的用法:
|
||||
|
||||
```
|
||||
RENAME(1) Linux Programmer’s Manual RENAME(1)
|
||||
|
||||
NAME
|
||||
rename - Rename files
|
||||
|
||||
SYNOPSIS
|
||||
rename from to file...
|
||||
rename -V
|
||||
|
||||
DESCRIPTION
|
||||
rename will rename the specified files by replacing the first occurrence of from in their name by to.
|
||||
|
||||
-V, --version
|
||||
Display version information and exit.
|
||||
|
||||
For example, given the files
|
||||
foo1, ..., foo9, foo10, ..., foo278, the commands
|
||||
|
||||
rename foo foo0 foo?
|
||||
rename foo foo0 foo??
|
||||
|
||||
will turn them into foo001, ..., foo009, foo010, ..., foo278.
|
||||
|
||||
And
|
||||
rename .htm .html *.htm
|
||||
|
||||
will fix the extension of your html files.
|
||||
|
||||
SEE ALSO
|
||||
mmv(1), mv(1)
|
||||
|
||||
AVAILABILITY
|
||||
The rename command is part of the util-linux-ng package and is available from ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
|
||||
|
||||
1 January 2000 RENAME(1)
|
||||
```
|
||||
|
||||
需要注意的是,rename使用时需要有三个参数。而且注意一下rename的通配符:
|
||||
|
||||
```
|
||||
? 可替代单个字符
|
||||
* 可替代多个字符
|
||||
* [charset] 可替代charset集中的任意单个字符
|
||||
```
|
|
@ -0,0 +1,73 @@
|
|||
这八个建议,来源于键者几年来编写 shell 脚本的一些经验和教训。事实上开始写的时候还不止这几条,后来思索再三,去掉几条无关痛痒的,最后剩下八条。毫不夸张地说,每条都是精挑细选的,虽然有几点算是老生常谈了。
|
||||
|
||||
## 1. 指定bash
|
||||
shell 脚本的第一行,#!之后应该是什么?如果拿这个问题去问别人,不同的人的回答可能各不相同。
|
||||
我见过/usr/bin/env bash,也见过/bin/bash,还有/usr/bin/bash,还有/bin/sh,还有/usr/bin/env sh。这算是编程界的“'茴'字四种写法”了。
|
||||
|
||||
在多数情况下,以上五种写法都是等价的。但是,写过程序的人都知道:“少数情况”里往往隐藏着意想不到的坑。
|
||||
|
||||
如果系统的默认 shell 不是 bash 怎么办?比如某 Linux 发行版的某个版本,默认的 sh 就不是 bash。
|
||||
如果系统的 bash 不是在 /usr/bin/bash 怎么办?
|
||||
|
||||
我推荐使用 /usr/bin/env bash 和 /bin/bash。前者通过env添加一个中间层,让env在$PATH中搜索bash;后者则是官方背书的,约定俗成的 bash 位置,/usr/bin/bash不过是指向它的一个符号链接。
|
||||
|
||||
|
||||
## 2. set -e 和 set -x
|
||||
OK,经过一番讨论,现在第一行定下来了。接下来该开始写第二行了吧?
|
||||
且慢!在你开始构思并写下具体的代码逻辑之前,先插入一行set -e和一行set -x。
|
||||
|
||||
set -x会在执行每一行 shell 脚本时,把执行的内容输出来。它可以让你看到当前执行的情况,里面涉及的变量也会被替换成实际的值。
|
||||
|
||||
set -e会在执行出错时结束程序,就像其他语言中的“抛出异常”一样。(准确说,不是所有出错的时候都会结束程序,见下面的注)
|
||||
|
||||
注:set -e结束程序的条件比较复杂,在man bash里面,足足用了一段话描述各种情景。大多数执行都会在出错时退出,除非 shell 命令位于以下情况:
|
||||
|
||||
一个 pipeline 的非结尾部分,比如 error | ok
|
||||
一个组合语句的非结尾部分,比如 ok && error || other
|
||||
一连串语句的非结尾部分,比如 error; ok
|
||||
位于判断语句内,包括test、if、while等等。
|
||||
这两个组合在一起用,可以在 debug 的时候替你节省许多时间。出于防御性编程的考虑,有必要在写第一行具体的代码之前就插入它们。扪心自问,写代码的时候能够一次写对的次数有多少?大多数代码,在提交之前,通常都经历过反复调试修改的过程。与其在焦头烂额之际才引入这两个配置,不如一开始就给 debug 留下余地。在代码终于可以提交之后,再考虑是否保留它们也不迟。
|
||||
|
||||
## 3. 带上shellcheck
|
||||
好了,现在我已经有了三行(样板)代码,具体的业务逻辑一行都没写呢。是不是该开始写了?
|
||||
且慢!工欲善其事,必先利其器。这次,我就介绍一个 shell 脚本编写神器:shellcheck
|
||||
|
||||
说来惭愧,虽然写了几年 shell 脚本,有些语法我还是记不清楚。这时候就要依仗 shellcheck 指点一下了。shellcheck 除了可以提醒语法问题以外,还能检查出 shell 脚本编写常见的 bad code。本来我的N条建议里面,还有几条是关于这些 bad code 的,不过考虑到 shellcheck 完全可以发掘出这些问题,于是忍痛把它们都剔除在外了。毫无疑问,使用 shellcheck 给我的 shell 编写技能带来了巨大的飞跃。
|
||||
|
||||
|
||||
所谓“站在巨人的肩膀上”,虽然我们这些新兵蛋子,技能不如老兵们强,但是我们可以在装备上赶上对方啊!动动手安装一下,就能结识一个循循善诱的“老师”,何乐而不为?
|
||||
|
||||
顺便一提,shellcheck 居然是用 haskell 写的。谁说 haskell 只能用来装逼?
|
||||
|
||||
## 4. 变量展开
|
||||
在 shell 脚本中,偶尔可以看到这样的做法:echo $xxx | awk/sed/grep/cut... 。看起来大张形势的样子,其实不过是想修改一个变量的值。杀鸡何必用牛刀?bash内建的变量展开机制已经足以满足你各种需求!还是老方法, read the f**k manaul! man bash 然后搜索Parameter Expansion,下面就是你想要的技巧。键者也写过一篇相关的文章,希望能助上一臂之力:玩转Bash变量
|
||||
|
||||
## 5. 注意local
|
||||
随着代码越写越多,你开始把重复的逻辑提炼成函数。有可能你会掉到bash的一个坑里。在bash,如果不加 local 限定词,变量默认都是全局的。变量默认全局——这跟 js 和 lua 相似;但相较而言,很少有 bash 教程一开始就告知你这个事实。在顶级作用域里,是否是全局变量并不重要。但是在函数里面,声明一个全局变量可能会污染到其他作用域(尤其在你根本没有注意到这一点的情况下)。所以,对于在函数内声明的变量,请务必记得加上 local 限定词。
|
||||
|
||||
## 6. trap信号
|
||||
如果你写过稍微复杂点的在后台运行的程序,应该知道 posix 标准里面“信号”是什么一回事。如果不知道,直接看下一段。像其他语言一样,shell 也支持处理信号。trap sighandler INT可以在接收到 SIGINT 时调用 sighandler 函数。捕获其他信号的方式以此类推。
|
||||
|
||||
不过 trap 的主要应用场景可不是捕获哪个信号。trap 命令支持“捕获”许多不同的流程——准确来说,允许用户给特定的流程注入函数调用。其中最为常用的是trap func EXIT和trap func ERR。
|
||||
|
||||
trap func EXIT允许在脚本结束时调用函数。由于无论正常退出抑或异常退出,所注册的函数都能得以调用,在需要调用一个清理函数的场景下,我都是用它注册清理函数,而不是简单地在脚本结尾调用清理函数。
|
||||
|
||||
trap func ERR允许在运行出错时调用函数。一个常用的技法是,使用全局变量ERROR存储错误信息,然后在注册的函数中根据存储的值完成对应的错误报告。把原本四分五裂的错误处理逻辑集中到一处,有时候会起奇效。不过要记住,程序异常退出时,既会调用EXIT注册的函数,也会调用ERR注册的函数。
|
||||
|
||||
## 7. 三思后行
|
||||
以上几条都是具体的建议,剩下两条比较务虚。
|
||||
|
||||
这条建议的名字叫“三思而行”。其实无论写什么代码,哪怕只是一个辅助脚本,都要三思而行,切忌粗心大意。不,写脚本的时候更要记住这点。毕竟许多时候,一个复杂的脚本发端于几行小小的命令。一开始写这个脚本的人,也许以为它只是一次性任务。代码里难免对一些外部条件有些假定,在当时也许是正常的,但是随着外部环境的变化,这些就成了隐藏的暗礁。雪上加霜的是,几乎没有人会给脚本做测试。除非你去运行它,否则不知道它是否还能正常使用。
|
||||
|
||||
要想减缓脚本代码的腐烂速度,需要在编写的时候辨清哪些是会变的依赖、哪些是脚本正常运行所不可或缺的。要有适当的抽象,编写可变更的代码;同时要有防御性编程的意识,给自己的代码一道护城河。
|
||||
|
||||
## 8. 扬长避短
|
||||
有些时候,使用 shell 写脚本就意味着难以移植、难以统一地进行错误处理、难以利索地处理数据。
|
||||
虽然使用外部的命令可以方便快捷地实现各种复杂的功能,但作为硬币的反面,不得不依靠grep、sed、awk等各种工具把它们粘合在一起。
|
||||
如果有兼容多平台的需求,还得小心规避诸如BSD和GNU coreutils,bash版本差异之类奇奇怪怪的陷阱。
|
||||
由于缺乏完善的数据结构以及一致的API,shell 脚本在处理复杂的逻辑上力不从心。
|
||||
|
||||
解决特定的问题要用合适的工具。知道什么时候用 shell,什么时候切换到另外一门更通用的脚本语言(比如ruby/python/perl),这也是编写可靠 shell 脚本的诀窍。如果你的任务可以组合常见的命令来完成,而且只涉及简单的数据,那么 shell 脚本就是适合的锤子。如果你的任务包含较为复杂的逻辑,而且数据结构复杂,那么你需要用ruby/python之类的语言编写脚本。
|
||||
|
||||
|
||||
PS:文中提到的几个点,博主在平时实践中也有所体会。没有找到原文的原始出处,所以没有给出原始链接。
|
|
@ -0,0 +1,61 @@
|
|||
## 1.打开/前往
|
||||
⌘T 前往文件
|
||||
⌘⌃P 前往项目
|
||||
⌘R 前往 method
|
||||
⌘⇧P 命令提示
|
||||
⌃G 前往行
|
||||
⌘KB 开关侧栏
|
||||
⌃ ` python 控制台
|
||||
⌘⇧N 新建窗口
|
||||
|
||||
## 编辑
|
||||
⌘L 选择行 (重复按下将下一行加入选择)
|
||||
⌘D 选择词 (重复按下时多重选择相同的词进行多重编辑)
|
||||
⌃⇧M 选择括号内的内容
|
||||
⌘⇧↩ 在当前行前插入新行
|
||||
⌘↩ 在当前行后插入新行
|
||||
⌃⇧K 删除行
|
||||
⌘KK 从光标处删除至行尾
|
||||
⌘K⌫ 从光标处删除至行首
|
||||
⌘⇧D 复制(多)行
|
||||
⌘J 合并(多)行
|
||||
⌘KU 改为大写
|
||||
⌘KL 改为小写
|
||||
⌘ / 注释
|
||||
⌘⌥ / 块注释
|
||||
⌘Y 恢复或重复
|
||||
⌘⇧V 粘贴并自动缩进
|
||||
⌃ space 自动完成(重复按下选择下一个提示)
|
||||
⌃M 跳转至对应的括号
|
||||
⌘U 软撤销(可撤销光标移动)
|
||||
⌘⇧U 软重做(可重做光标移动)
|
||||
XML/HTML
|
||||
⌘⇧A 选择标签内的内容
|
||||
⌘⌥ . 闭合当前标签
|
||||
|
||||
## 查找/替换
|
||||
⌘F 查找
|
||||
⌘⌥F 替换
|
||||
⌘⌥G 查找下一个符合当前所选的内容
|
||||
⌘⌃G 查找所有符合当前所选的内容进行多重编辑
|
||||
⌘⇧F 在所有打开的文件中进行查找
|
||||
|
||||
## 拆分窗口/标签页
|
||||
⌘⌥1 单列
|
||||
⌘⌥2 双列
|
||||
⌘⌥5 网格 (4组)
|
||||
⌃[1,2,3,4] 焦点移动至相应组
|
||||
⌃⇧[1,2,3,4] 将当前文件移动至相应组
|
||||
⌘[1,2,3…] 选择相应标签页
|
||||
|
||||
## 书签
|
||||
⌘F2 添加/去除书签
|
||||
F2 下一个书签
|
||||
⇧F2 前一个书签
|
||||
⌘⇧F2 清除书签
|
||||
|
||||
## 标记
|
||||
⌘K space 设置标记
|
||||
⌘KW 从光标位置删除至标记
|
||||
⌘KA 从光标位置选择至标记
|
||||
⌘KG 清除标记
|
|
@ -0,0 +1,8 @@
|
|||
mac中,sublime全部查找替换的快捷键为option + cmd + f
|
||||
|
||||
现在要想批量在行首添加注释,可以有以下操作:
|
||||
先按option + cmd + f,在find what中输入 ^,查找到所有的行首,然后就可以在行首批量添加。
|
||||
同理,要想在行末批量添加,
|
||||
先按option + cmd + f,在find what中输入 $,查找到所有的行尾,然后就可以在行尾批量添加。
|
||||
|
||||
需要注意的是,以上操作需要将左下方的Regular expression激活,因为^,$是正则表达式的写法
|
Loading…
Reference in New Issue