
14

终端 10X 工作法
source link: http://legendtkl.com/2019/11/11/terminal-10x-bash/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在 github 上面有一个 700 多人 star 的 repo 叫做 Bash-Oneliner,介绍了很多实用并且可以有效提高工作效率的命令,我们来了解一下。原文直达:Bash-Oneliner 。注:去除了部分看上去没啥用的命令,可以原文查看所有内容。
1. Terminal
注:下面介绍的是在 Linux 下的 terminal 的行为,在 Mac 下面会略有差异,尽量补全
Ctrl 相关
Ctrl + n : 类似向下方向键
Ctrl + p : 类似向上方向键
Ctrl + r : 反向搜索 terminal 的历史命令
Ctrl + s : 停止该 terminal
Ctrl + q : 在 Ctrl + s 后面重新恢复该 terminal
Ctrl + a : 移动光标到行的开始处。(这个很有用)
Ctrl + e : 移动光标到行的结尾处。(同上)
Ctrl + d : 如果当前的 terminal 的命令行有输入,那么 Ctrl + d 会删除光标处的数字。否则会退出当前的 terminal
Ctrl + k : 删除从当前光标开始到结尾的所有的字符
Ctrl + x + backspace: 删除从当前光标到行开始的所有的字符
Ctrl + t : 交换当前光标下的字符和其前面的字符的位置。Esc + t 交换光标前面的两个单词。(这个很有意思)
Ctrl + w : 剪切光标之前的单词。Ctrl + y 粘贴该单词
Ctrl + u : 剪切光标之前的所有字符。Ctrl + y 粘贴刚刚剪切的字符
Ctrl + _ : 撤销前面的操作。(可以连续操作多次)
Ctrl + l : 类似 clear。(类似 Mac 终端下的 Command + k)
Ctrl + x + Ctrl + e : 唤起 $EDITOR 环境变量设置的编辑器程序,在需要输入多行的情况下比较有用。(试验了一下如果之前没有设置,$EDITOR 的默认值是 emacs。你可以将其设置为 vim,即 export EDITOR=vim。当然也可以将这个环境变量设置为其他的应用程序去实现一些有趣的功能,这个测试过了)
改变字符大小写
Esc + u : 将当前光标开始到单词结尾的字符都转换成大写。(这里的单词指的是光标所在的位置前后以空格分隔形成的单词)
Esc + l : 将当前光标开始到单词结尾的字符都转换成小写
Esc + c : 将光标所在位置的字符转换成大写
执行历史命令
!53 : 执行 history 中的 53 号命令
!! : 执行上一条命令
替换上一条命令,并替换一些参数
# 上一条命令:echo 'aaa'
^aaa^bbb
# 此时将上一条命令替换为 echo 'bbb',输出 bbb
# 需要注意的是,这样只会替换第一次 aaa,如果要替换所有的 aaa,需要像下面这样使用
^aaa^bbb^:&
# 或者
!!:gs/aaa/bbb/
前缀匹配执行历史命令
!cat
# 或者
!c
# 执行历史命令中最近一条满足前缀是 c 或者 cat 的命令
文件名使用正则
# ? 表示一个单独的任意字符
/b?n/?at # 匹配上 /bin/cat
# * 表示多个任意字符
/etc/pa*wd # 匹配上 /etc/passwd
# '[]' 表示一个字符范围
ls -al [a-z]* # 列出所有以字母开头的文件
# '{}' 文件名匹配多种模式
ls {*.sh,*.py} # 列出所有的 .sh 和 .py 文件
$0, $1, $2, $3, ... : 在执行 shell 的时候传参使用,$0 表示 shell 名字,$1,$2,$3依次表示后面的参数
$# : 参数的个数
$? : 最近的一个终端 foreground 命令的退出状态
$- : 当前 shell 设置的选项,可以通过 echo $- 查看
$$ : 当前 shell 进程的 pid
$! : 最近的一个终端后台命令的 pid
$DESKTOP_SESSION : 当前的展示管理器。(可能说的是 xWindow)
$EDITOR : 编辑器,可以通过上面提到的快捷键唤醒
$LANG : 语言设置
$PATH : 这个不用说了
$PWD : 当前目录
$SHELL : 当前的 shell
$USER : 当前的 username
$HOSTNAME : 当前的 hostname
2. Grep
grep 的种类
grep = grep -G # 支持基本的正则表达式
fgrep = grep -F # 查找文件里符合条件的字符串
egrep = grep -E # 支持扩展的正则表达式
pgrep = grep -P # 兼容 Perl 的正则表达式语法
rgrep = grep -r # 递归 grep
统计空行个数
grep -c "^$"
grep 并且只返回数字
grep -o '[0-9]*'
#或者
grep -oP '\d'
grep 含有特定数字的数字
grep ‘[0-9]\{3\}’
# or
grep -E ‘[0-9]{3}’
# or
grep -P ‘\d{3}’
查找 IP 地址
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
# or
grep -Po '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
# return also 3 lines after match
grep -A 3 'bbo'
# return also 3 lines before match
grep -B 3 'bbo'
# return also 3 lines before and after match
grep -C 3 'bbo'
查找特定字符开头的单词
grep -o 'S.*'
提取两个特定单词之间的文本
grep -o -P '(?<=w1).*(?=w2)'
查找不包含某个单词的文件内容
grep -v bbo filename
查找不是以特定字符开头的文件内容
grep -v '^#' file.txt
查找含有空格的内容
bbo="some strings"
grep "$boo" filename
查找第一个 match 文件内容
grep -m 1 bbo filename
查找并返回满足条件的文件内容条数
grep -c bbo filename
统计单词在文件中出现的次数
grep -o bbo filename |wc -l
大小写敏感的查找
grep -i "bbo" filename
匹配结果着色
grep --color bbo filename
查找目录下的所有文件
grep -R bbo /path/to/directory
# or
grep -r bbo /path/to/directory
查找目录下的所有文件,不输出文件内容
grep -rh bbo /path/to/directory
查找目录下的所有文件,只输出匹配的文件名
grep -rl bbo /path/to/directory
grep 'A\|B\|C\|D'
AND 查找(比如 A and B)
grep 'A.*B'
正则查找(比如 ACB 或者 AEB)
grep 'A.B'
查找特定字符(比如 color 或者 colour)
grep ‘colou?r’
查找多个文件的所有内容
grep -f fileA fileB
查找 tab
grep $'\t'
从变量中查找
$echo "$long_str"|grep -q "$short_str"
if [ $? -eq 0 ]; then echo 'found'; fi
#grep -q will output 0 if match found
#remember to add space between []!
查找括号中间的字符串
grep -oP '\(\K[^\)]+'
略过目录查找
grep -d skip 'bbo' /path/to/files/*
3. Sed
移除文件第一行
sed 1d filename
移除文件的前 100 行
sed 1,100d filename
移除包含特定字符串的文件行
注:这种方式并不会修改原文件,可以将输出重定向到新的文件保存
sed "/bbo/d" filename
# case insensitive:
sed "/bbo/Id" filename
移除文件不满足第 n 个字符串不等于某个值的行
# 第 5 个字符不等于 2
sed -E '/^.{5}[^2]/d'
#aaaa2aaa (you can stay)
#aaaa1aaa (delete!)
修改原文件
# 删除包含 bbo 的行并直接保存文件
sed -i "/bbo/d" filename
使用变量的时候使用双引号
# e.g. add >$i to the first line (to make a bioinformatics FASTA file)
sed "1i >$i"
# notice the double quotes! in other examples, you can use a single quote, but here, no way!
# '1i' means insert to first line
sed '/^\s*$/d'
# or
sed '/^$/d'
删除最后一行
sed '$d'
删除文件的最后一个字符
sed -i '$ s/.$//' filename
向文件开头插入字符串(比如 “[“)
sed -i '1s/^/[/' file
向文件中特定行中插入字符串
sed -e '1isomething' -e '3isomething'
向文件结尾插入字符(比如 “]”)
sed '$s/$/]/' filename
向文件结尾插入新行
sed '$a\'
向文件的每一行插入数据
sed -e 's/^/bbo/' file
向文件的每一行结尾插入数据
sed -e 's/$/\}\]/' filename
每 n 个字符插入换行符(比如每 4 个字符)
sed 's/.\{4\}/&\n/g'
连接多个文件
sed -s '$a,' *.json > all.json
sed 's/A/B/g' filename
基于正则的文件内容替换
sed "s/aaa=.*/aaa=\/my\/new\/path/g"
筛选文件中以特定字符串开始行
sed -n '/^@S/p'
####打印文件中的多行
sed -n 500,5000p filename
打印文件中特定行
sed -n '0~3p' filename
# 打印 3 的倍数行
打印奇数行
sed -n '1~2p' filename
删除文件开头的空格和 tab
sed -e 's/^[ \t]*//'
# Notice a whitespace before '\t'!!
只删除空格
sed 's/ *//'
# notice a whitespace before '*'!!
移除文件结尾的逗号
sed 's/,$//g'
文件结尾添加一列(以 tab 分隔)
sed "s/$/\t$i/"
# $i is the valuable you want to add
# To add the filename to every last column of the file
for i in $(ls);do sed -i "s/$/\t$i/" $i;done
打印特定的行
sed -n -e '123p'
删除文件的最后一个字符
sed '$ s/.$//'
指定位置插入字符
sed -r -e 's/^.{3}//' file
4. Awk
设置 tab 为分隔符
awk -F $'\t'
设置 tab 为输出内容的分隔符
awk -v OFS='\t'
a=bbo;b=obb;
awk -v a="$a" -v b="$b" "$1==a && $10=b" filename
输出文件行号以及每行的字符个数
awk '{print NR,length($0);}' filename
输出 column/field 的个数
awk '{print NF}'
判断是不是有逗号
awk '$1~/,/ {print}'
输出字符串出现 n 次之前的所有行
awk -v N=7 '{print}/bbo/&& --N<=0 {exit}'
输出文件名和其最后一行
ls|xargs -n1 -I file awk '{s=$0};END{print FILENAME,s}' file
向指定的 column 插入字符串
awk 'BEGIN{OFS="\t"}$3="chr"$3'
移除包含特定字符串的行
awk '!/bbo/' file
移除最后一个 column
awk 'NF{NF-=1};1' file
理解 NR 和 FNR 的作用
# For example there are two files:
# fileA:
# a
# b
# c
# fileB:
# d
# e
awk 'print FILENAME, NR,FNR,$0}' fileA fileB
# fileA 1 1 a
# fileA 2 2 b
# fileA 3 3 c
# fileB 4 1 d
# fileB 5 2 e
5. Xargs
设置 tab 为分隔符
xargs -d\t
每行显示三个元素
echo 1 2 3 4 5 6| xargs -n 3
# 1 2 3
# 4 5 6
执行之前先询问
$ echo a b c |xargs -p -n 3
$ echo a b c ?... #输入 y
$ a b c
find 文件并删除
find . -name "*.html"|xargs rm
删除文件名中含有空格的文件
find . -name "*.c" -print0|xargs -0 rm -rf
显示 limits
xargs --show-limits
find . -name "*.bak" -print 0|xargs -0 -I {} mv {} ~/old
# or
find . -name "*.bak" -print 0|xargs -0 -I file mv file ~/old
ls |head -100|xargs -I {} mv {} d1
time echo {1..5} |xargs -n 1 -P 5 sleep
# a lot faster than:
time echo {1..5} |xargs -n1 sleep
基于条件的文件拷贝
find /dir/to/A -type f -name "*.py" -print 0| xargs -0 -r -I file cp -v -p file --target-directory=/path/to/B
# v: verbose|
# p: keep detail (e.g. owner)
和 sed 配合使用
ls |xargs -n1 -I file sed -i '/^Pos/d' filename
将文件名加入到文件的第一行
ls |sed 's/.txt//g'|xargs -n1 -I file sed -i -e '1 i\>file\' file.txt
ls |xargs -n1 wc -l
将输出整合到一行
ls -l| xargs
统计文件夹下面各个文件的行数和总的行数
ls|xargs wc -l
和 grep 联合使用
cat grep_list |xargs -I{} grep {} filename
和 sed 联合使用
grep -rl '192.168.1.111' /etc | xargs sed -i 's/192.168.1.111/192.168.2.111/g'
6. Find
递归列出所有的子目录和文件
find .
列出当前目录下的所有文件
find . -type f
列出当前目录下的所有子目录
find . -type d
修改当前目录下的所有文件(将 ‘www’ 替换成 ‘w’)
find . -name '*.php' -exec sed -i 's/www/w/g' {} \;
# if there are no subdirectory
replace "www" "w" -- *
# a space before *
删除大小小于 74 byte 的文件
find . -name "*.mso" -size -74c -delete
# M for MB, etc
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK