Shell 常用命令、基本用法总结

Filter

Filter 常用于从大量文本、数据中提取需求的部分。下面介绍几个常用的 filter 命令。

cut

$ cut -c 5-8 textfile.txt 	    # 切出 textfile.txt 中每行的第 5 到第 8 个 character
$ cut -f2-4 -d',' textfile.txt 	# 切出 textfile.txt 中每行的第 2 到第 4 块 field,field 由 delimiter “,” 确定
$ cut -f2,4 -d'|' textfile.txt	# 切出 textfile.txt 中每行的第 2 、第 4 块 field, field 由 delimiter “|” 确定

uniq

$ sort | uniq -c	# aggregation (带 count),类似 SQL 中的 GROUPBY

egrep

$ egrep -o <pattern> textfile.txt	# 只返回 match pattern 的部分
$ egrep -x <pattern> textfile.txt	# 只有文件的某行 (line) fully match pattern 的时候才返回
$ egrep -w <pattern> textfile.txt	# 只有文件的某字 (word) fully match pattern 的时候才返回

wc

$ wc -l textfile.txt		# 返回行数计数
$ wc -m textfile.txt		# 返回char计数
$ wc -w textfile.txt		# 返回word计数

tr

$ tr  <srcChars> <destChars>	# 将输入字符中含有 srcChars 的字符对应替换成 destChars
$ tr  'a-z' 'A-Z'				# 将输入字符的小写字母转为大写
$ tr -d ' '						# 删除输入字符中所有的空格
$ tr -cs 'a-zA-Z0-9' '\n' 		# 切出在 SET 'a-zA-Z0-9' 中的连续字符,并按行输出

sed

$ sed 's/regex/replacement/ig'	# 将 match regex 的部分全部替换成 replacement
$ sed -E -n 's/regex-with-capture-group/\1/p' # 用regex的group capture提取子串
$ sed -E -n '/regex/p'  # mimic grep -E 'regex'

cat

$ cat >new_textfile.txt<<eof	# 新建并从 stdin 按行写入文件 new_textfile.txt,直到遇到 eof 结束
$ cat >>new_textfile.txt<<eof	# 从 stdin 按行连接写入文件 new_textfile.txt,直到遇到 eof 结束

ps

$ ps -eo pid,user:20,cmd |grep $pid  # 查询PID的用户名、命令

Shell Script 入门

介绍 Shell 的一些常识和基本用法。

准备工作

Shell 脚本文件头

#!/bin/bash		# 告诉 Linux 该文件用 bash 运行

可执行模式

$ chmod +x shell_script.sh	# 修改 shell_script.sh 为可执行文件

常用命令

SSH

远程连接服务器(以 AWS 为例)
如果要连接 AWS, 需要联系管理员拿到私钥文件(扩展名为 .pem)。

$ ssh -i "private-key.pem" user_name@domain_name

如果想在 AWS 上运行 jupyter,tensorboard 等任务,可以使用 local forwarding 功能,将本地操作转发到远端服务器:

$ ssh -i "private-key.pem" <local-port>:127.0.0.1:<remote-port> user_name@domain_name

ALIAS

给一些常用命令+参数设置别名

alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
alias python3='python3.7'
alias scp='scp -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" -o "PasswordAuthentication yes"'
alias ssh='ssh -o "StrictHostKeyChecking no" -o "UserKnownHostsFile /dev/null" -o "PasswordAuthentication yes"'

sudo update-alternatives --install /usr/local/bin/python3 python3 /usr/local/bin/python3.11 1

STDIN

$ read a_str_variable		# 从 stdin 读取字符串存入 a_str_variable 变量
$ read -t 3 a_str_variable	# 3s 内无输入则退出(返回值 142)
$ read -s a_str_variable	# 不显示输入字符,输入密码等机密信息时使用
$ read -p "Name? "			# 相当于 Python 中的 input("Name? ")
$ read -r a_str_variable	# 当输入的字符中含 “\” (反斜杠)时,保留 “\”。如果没有设置 -r,则反斜杠都会被 “吃掉”
							# 参考:https://unix.stackexchange.com/questions/18886/why-is-while-ifs-read-used-so-often-instead-of-ifs-while-read/18936#18936

STDOUT

$ echo string

图片转换

$ convert original_image.png converted_image.jpg	# 图片格式转换,支持格式:jpg, png, gif, bmp, tif
$ convert -gravity south \				# 设置 draw text 的位置
			  -pointsize 36 \			# 设置字体大小
			  -draw "text 0,10 'Hello world'" original_image.jpg converted.jpg

文件搜索

$ find 							# 递归输出当前目录及其下所有文件或子目录,相当于`find . -print`
$ find dir						# 递归输出dir 目录及其下所有文件或子目录
$ find dir -type f				# 递归输出dir 目录下的所有文件
$ find dir -type d				# 递归输出dir 目录及其下的所有子目录
$ find dir -name '*s2_COMP9041'	# 递归输出dir 目录下所有符合通配符 `*s2_COMP9041` 的文件名或目录名(*此处不匹配斜杠/)
$ find dir -iname '*s2_comp9041'# 递归输出dir 目录下所有符合通配符 `*s2_comp9041` 的文件名或目录名(*此处不匹配斜杠/)(case insensitive)
$ find dir -path '*.sh'			# 递归输出dir 目录下所有符合通配符 `*.sh` 的文件路径或目录路径(*此处匹配斜杠/)
$ find dir -ipath '*.SH'		# 递归输出dir 目录下所有符合通配符 `*.sh` 的文件路径或目录路径(*此处匹配斜杠/)(case insensitive)
$ find dir -path '*.sh' \		# <或>操作
		   -or -path '*.pl' \
		   -or -path '*.py'
$ find dir -not -name '*.sh' \	# <非>操作
		   -type f
$ find dir -path '*.tmp' \		# <与>操作
		   -type f -delete		# 递归删除dir 目录下所有路径符合通配符 `*.tmp` 的文件
$ find dir -name '*s2_COMP9041'\# 递归遍历dir 目录下所有
		   -type d \			# 的目录名
		   -prune				# 如果目录名符合通配符 `'*s2_COMP9041'`,该目录下所有内容都被忽略
		   -print				# 并输出(该选项可省略)
$ find dir -name '*s2_COMP9041'\# 递归遍历dir 目录下所有
		   -type d \			# 的目录名
		   -prune				# 如果目录名符合通配符 `'*s2_COMP9041'`,该目录下所有内容都被忽略
		   -or -print			# 输出其它未被忽略的目录及文件

# 有时可能仅仅需要排除目录,而非连同该目录下的所有文件。此时需要用到 -depth 选项
$ find dir -depth \				# 规定遍历顺序:遇到目录时,先列出目录中的文件,再列出目录自己
		   -name '*s2_COMP9041'\# 递归遍历dir 目录下所有
		   -type d \			# 的目录名
		   -prune				# 如果目录名符合通配符 `'*s2_COMP9041'`,该目录下所有内容都被忽略
		   -or -print			# 输出其它未被忽略的目录及文件
# 参考:https://math2001.github.io/post/bashs-find-command/

条件判断

#!/bin/bash

# 参数个数检查
if test $# -ne 2	
# 或 if [ $# -ne 2 ]
# 或 if (( $# != 2 ))
then 
  echo Usage: "$0": '<non-negtive_int> <string>'
  exit 1
fi

# 参数类型检查
if test $1 -ge 0
# 或 if [ $1 -ge 0 ]
then 
  :
else
  echo "$0": argument 1 must be a non-negtive integer!
  exit 2
fi

# 程序逻辑开始...

for Loop

# 遍历当前目录中的所有文件名
## Version 1 ## 不包括隐藏文件 ##
$ shopt -u dotglob
$ for filename in *
> do echo $filename
> done

## Version 2 ## 包括隐藏文件 ##
$ shopt -s dotglob
$ for filename in *
> do echo $filename
> done
## 根据 argument 输入的目录路径 `important_files/*` 遍历其中(包括子目录)所有的文件
# Input: $ readfile.sh important_files/*
$ for paths in "$@"	# 注意! 1.不是$1 2.Add double quotes
> do 
>   find $paths -type f -print0 |
>   while read -d $'\0' path
>   do echo $path
>   done
> done
# 类似 C语言 的用法
$ begin=0; end=5; step=1
$ for ((i=$begin; ((i < $end)); ((i += $step)) ))
> do echo $i
> done
# write files from arguments by line with line number
line_no=0
for word in "$@"
do
  ((line_no+=1))
  echo $line_no $word
done > filepath

while Loop

# 类似 C语言 的用法
$ begin=0; end=5; step=1
$ i=$begin
$ while test $i -lt $end <OR> while [ $i -lt $end ] <OR> while (( i < end ))
> do echo $i
>    (( i+=step ))
> done
# read files by line
while read line
do
  echo $line
done < filepath

sh

$ sh -x your_shell_script.sh	# 用于追踪程序流,debug 时很实用

一些细节

Silence

$ egrep 'regex' filename.txt >/dev/null 2>&1	# >/dev/null —— stdout(1) 被扔到 /dev/null
							# >2>&1      —— stderr(2) 跟着 stdout(1) 走
							# 总结:不在屏幕上打印 stdout 和 stderr

引号问题,date 用法,图片处理

# 实际应用:给图片打tag
$ date_time=`date "+%H:%M %d %b,%Y"`
$ convert -draw "text 0,0 '$date_time'" oringal.jpg tagged.jpg

Linux 文件名相关问题

文件名以 “-” 开头

$ mv -- filename(以‘-’开头) newfilename		# -- 表示下一个参数不会是 Option(必须是文件名)

文件名中绝对不能包含的字符

['/', '\0']

文件名大小写敏感

$ touch important_file.db Important_File.Db IMPORTANT_FILE.DB
$ ls
important_file.db Important_File.Db IMPORTANT_FILE.DB
posted @ 2018-08-11 17:04  LexLuc  阅读(2625)  评论(0编辑  收藏  举报