Linux使用技巧
Docker
Docker is a tool to run Linux containers based on selected images.
Docker从入门到实践
Win10家庭版用WSL2运行Docker Desktop,将数据从C盘迁移到其他目录
Win10开始使用Hyper-V运行docker,家庭版无此功能,所以只能pro版本才能用docker desktop。后来升级到2004系统后,家庭版可升级WSL(Windows Subsystem for Linux)至WSL2,便可基于WSL2运行docker desktop,但相较于Hyper-V的区别在于,其数据由WSL2代为管理,无法在docker里设置镜像存储路径。
安装docker后,docker会自动创建2个发行版:docker-desktop
和docker-desktop-data
,其默认安装在C盘,在%LOCALAPPDATA%/Docker/wsl
目录里,而docker的运行数据、镜像文件都存在%LOCALAPPDATA%/Docker/wsl/data/ext4.vhdx
中,比较占用C盘空间,故考虑将其迁移至D盘。
对于WSL发行版的迁移,网上教程基本均需使用LxRunOffline,但其虽然可以迁移例如Ubuntu的发行版,但迁移不了docker自动创建的2个发行版。故考虑如下两种方式:
方法一:使用wsl命令
关闭docker desktop
关闭所有发行版
导出docker-desktop-data
注销docker-desktop-data
重新导入docker-desktop-data
注:只迁移docker-desktop-data即可,另一个占用空间较小
方法二:修改注册表(未直接验证,理论上及其他操作证明应当可行)
关闭docker desktop
打开
powershell
,输入whoami /user
,获得[SID];用wsl --shutdown
命令关闭所有发行版运行
regedit
,跳转至HKEY_USERS\[SID]\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss
在下属的文件文件夹中(文件夹名为一个UUID)找到
DistributionName
为docker-desktop-data
的项将其
BasePath
改为目标目录,如\\?\D:\Tools\WSL\docker-desktop-data
,并将原目录下ext4.vhdx
拷贝至该目录重启即可使用
Docker创建共享文件夹
检查docker是否安装成功
装载镜像
创建共享文件夹
创建容器(win10下共享文件夹需用绝对路径)
将docker中的
/home/test/share
由root
所有改为test
所有
以
test
用户运行docker
注:以
root
用户运行docker
鳥哥的Linux私房菜
Linux常用命令
Linux特殊符号
三十分钟学会AWK
三十分钟学会SED
Learn Vim Progressively
http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
Linux查看系统基本信息
查看版本当前操作系统内核信息
查看当前操作系统版本信息
查看版本当前操作系统发行版信息
查看cpu相关信息,包括型号、主频、内核信息等
查看服务器名称
查看网络信息
查看磁盘信息
查看进程与用户信息
Bash和Sh的区别
Bash is the most commonly used linux shell.
sh(或Shell命令语言)是由POSIX标准描述的一种编程语言。它有很多实现(ksh88, dash,…)。bash也可以被认为是sh的实现。因为sh是规范,不是实现,
/bin/sh
是在大部分POSIX系统上实际实现的符号连接(or 硬链接)。bash是兼容sh的一种实现(虽然在几年之前被视为POSIX标准),但随着时间流逝,它需要更多的扩展。这里面的一些扩展会改变有效的POSIX shell脚本的行为,所以bash本身不是有效的POSIX shell,而是POSIX shell语言的方言。但bash可以执行
--posix
切换,使得它更加的兼容POSIX,同时也尝试通过调用sh来模仿POSIX。长期以来,在大部分GNU/Linux系统上,
/bin/sh
都是指向/bin/bash
。结果,几乎可以忽略两者之间的区别了。但是这种情况最近开始改变。在
/bin/sh
不指向/bin/bash
(在某些情况下甚至都不存在/bin/bash
)的系统中,一些常见的例子是:现代的debian和ubuntu系统上,
sh
默认是dash
的符号链接Busybox,它通常在Linux系统引导时作为initramfs的一部分运行。它使用了ash shell实现。
BSDs,以及通常所有非linux系统。OpenBSD 使用pdksh,Korn shell的后代。FreeBSD的sh是原始UNIX Bourne shell的后代。Solaris有它自己的sh,但长期以来都不是与POSIX兼容的,是一种Heirloom项目提供的一个开源实现。
如何找到
/bin/sh
在我们系统上的指向/bin/sh
的复杂之处是:它可以是符号链接也可以是硬链接。如果是符号链接,可以尝试:
如果是硬链接,可以尝试:
注:实际上
-L
标志同时包括符号链接和硬链接,但是这种方法的缺点是它不是可移植的,POSIX不需要find
来支持-samefile
选项,尽管GNUfind
和FreeBSDfind
都支持它。
Shebang:在计算领域中,Shebang(也称为Hashbang)是一个由井号和叹号构成的字符序列#!,其出现在文本文件的第一行的前两个字符。最终,通过在脚本的第一行编写Shebang来决定使用sh还是bash。
利用.bashrc个性化配制bash环境
示例一
示例二
利用.vimrc个性化配置vim
复制一份vim配置模板到个人目录下
利用
vim
编辑该文件
保存退出
Bash下使用rsync
和crontab
备份文件
rsync
和crontab
备份文件Install
rsync
andcrontab
Prepare backup directory
Prepare a backup script, for example,
~/backup.sh
Using
crontab
command to execute the backup script routinely, and record in a log file, for example, execute the command~/backup.sh > ~/backup.log
in 5:10am everyday:add executable permission
open crontab and edit it by the following command:
type in the following lines or write the following in a file (i.e.
~/crontab
):
exit and save
Linux中for循环的几个常用写法
数字型循环
字符型循环
路径查找型循环
Linux下将文件夹命名为今天的日期的方法
Linux下使ls命令只显示目录的方法
附:ls与cd连用示例
Linux下替换^M
字符方法
^M
字符方法在Linux下使用vi
或cat -A
查看一些在Windows下创建的文本文件,有时会发现在行尾有一些^M
,是由于Linux的换行符为LF
,而Windows的换行符为CRLF
所造成。它的存在虽然不影响文件的一般查看,但会影响利用awk
、grep
等命令对文件进行操作,见下:
有如下解决方法:
使用
dos2unix
命令(建议所有在win下创建的文件均先在root用户下运行此命令转换一下格式)
使用vi的替换功能,在vi的命令模式下输入:
使用
sed
命令
注:在vim的.vimrc文件中把fileformat=unix去掉便不会显示(默认不显示^M)
附:Windows下使用git时保证为LF
格式
LF
格式Linux下将多行文件合并为一行
注意:对于win下文件(非linux创建),建议先运行
dos2unix
命令使用
awk
命令
使用
sed
命令:sed
默认按行处理,N
可以让其读入下一行,再对\n进行替换,这样就可以将两行并做一行。但为了将所有行并作一行,需要采用其跳转功能。:flag
在代码开始处设置一个标记flag
,在代码执行到结尾处时利用跳转命令t flag
重新跳转到标号flag
处,重新执行代码,这样就可以递归将所有行合并成一行。
使用
xargs
命令
附:文件合并、行筛选、多行合并脚本示例
Linux中cut命令
cut是一个选取命令,其以行为单位,选择性输出符合条件的内容到标准输出,使用格式为:
命令选项:
使用示例
Ubuntu镜像使用帮助
Ubuntu的软件源配置文件是
/etc/apt/sources.list
。将系统自带的该文件做个备份,再将该文件替换为下面内容,即可使用TUNA的软件源镜像。
Ubuntu下使用apt install XX(or sudo apt install XX)报错Unable to locate package
正常情况下,只需要更新软件列表
当上述命令无效时,尝试升级
注:一般情况下更改了软件源之后需要重新
update
Linux管理员修改普通用户密码
root修改普通用户的密码
普通用户修改自己的密码
Linux下使用sudo
命令出现not in the sudoers file
sudo
命令出现not in the sudoers file使用
su -
命令切换到root身份。注意该命令有-
,与su
不同,在用命令su
的时候只是切换到root,但没有把root的环境变量传过去,还是当前用户的环境变量,用su -
命令将环境变量也一起带过去,就像和root登录一样使用
visudo
命令编辑sudo
权限文件。注意,该命令为一个单词出现vim编辑窗口,在文件合适位置加入
<user_name> ALL=(ALL) ALL
语句保存退出后,便把自己加入了
sudo
组,可以使用sudo
命令了
Linux下安装Miniconda
进入清华大学开源软件镜像站 - Anaconda镜像使用帮助,下翻找到Miniconda镜像使用帮助
直接下载对应版本的
sh
文件,或将光标定位在所需文件,复制链接地址,再使用wget -c <url>
下载运行该文件,即执行命令
bash Miniconda***.sh
,根据提示按Enter键或者输入yes即可安装完成后,会在家目录
~
下生成一个Minconda3
文件夹运行
source .bashrc
,激活conda
,这时会发现终端前出现了(base)
,表示已进入conda
环境conda
安装成功之后,逐行运行下面的命令,添加国内镜像,方便以后下载软件。
注:若不希望终端前一直显示
base
,仅在需用conda
时才调用,可在.bashrc
最后加上一句conda deactivate
使其默认不运行。需使用时输入conda activate
激活之。
WSL更改登录用户
对于Ubuntu系统,在
Windows PowerShell
中运行ubuntu config --default-user <username>
即可
WSL中Vim字体改变的解决方案
问题:安装好WSL版本的Ubuntu1804之后,由于默认字体不适合长时间阅读且不美观,便从属性窗口设置了新字体,但是发现在启动Vim的时候会出现字体变回原来的字体的情况。
解决方法:运行
regedit
修改注册表,定位至HKEY_CURRENT_USER\Console\C:_Program Files_WindowsApps_CanonicalGroupLimited.Ubuntu18.04onWindows_1804<...>ubuntu1804.exe
,方括号中内容根据实际情况修改,在其中添加:CodePage
(DWORD
类型、值0x01b5
)
Linux字符串变量操作
截取
示例
取得字符串长度
字符串所在位置
从字符串开头到子串的最大长度
字符串截取
匹配内容
截取不匹配内容
比较
连接
删除与替换
巧记方法:
#
和%
是删除符号。在键盘上,#
在$
的左边,所以是从左边开始删除,%
在$
的右边,所以是从右边开始删除。/
是替换符。
示例
输出文件的后缀
输出文件名
替换部分字符
变量声明
Linux下nohup
命令
nohup
命令nohup
英文全称no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行。在默认情况下(非重定向时),程序会输出一个名叫 nohup.out 的文件到当前目录下,如果当前目录的 nohup.out 文件不可写,则输出重定向到 $HOME/nohup.out 文件中。
语法格式:
参数说明:
示例:
以下命令在后台执行1.sh脚本,并重定向输出到1.log文件:
如果要停止运行,你需要使用以下命令查找到nohup
运行脚本到PID,然后使用kill
命令来删除:
耗时很长的程序忘加nohup就运行了怎么办
按
Ctrl+z
把程序挂起,操作后屏幕会出现如下提示([1]中的1表示命令的作业号):
用
jobs
命令查看下任务状态,跟刚才的屏幕提示一致,程序被暂时终止,作业号还是1:
使用
bg %1
命令把作业号为1的任务放入后台,并从停止状态变为运行状态,相当于加了&
后接着运行。再用jobs
查看,任务状态变成了运行中。
运行
disown -h %1
,表示在终端关闭时不对作业号为1的程序发送终止信号,外部因素将不影响程序的运行。可通过ps命令查看任务进程。
提示:
例子中使用的是
rsync
同步,从节省时间来看,不是一个很好的例子。因为把命令停掉再运行一次时,已经同步完整的数据不会再同步,时间损失不会太大。这也是使用同步命令rsync
相比于scp
的一个好处。例子中的
rsync
或其它涉及两个服务器交互的命令,都需要我们人为输入登录密码,因此直接加nohup &
运行是行不通的,无法接受密码的输入。因此通过上面这个操作先在前台启动运行、输入密码,再放入后台不挂断运行。当然也可以使用ssh免密码登录远程服务器。如果程序运行时,已加了
&
放入后台了,则只需运行jobs
获得作业号,再运行disown
不挂断即可。程序作业号不一定都是1,如果之前就有程序在后台运行,作业号相应的会自加。
nohup
和disown
都可以使程序不挂断,可以获得一样的效果,但原理不太一致。nohup
可以使程序忽略挂断信号(SIGHUP)或者使程序脱离终端的控制,从而终端不能再对其发送挂断信号(SIGHUP);disown
则是内生于shell,告诉shell在终止时不对程序发送挂断信号(SIGHUP)。
awk基本操作符、内置函数与变量
awk操作符的优先级
awk内置函数
算术
字符串
其他
完整函数列表请查阅手册
awk内置变量
awk中同样定义了很多内置变量,我们可以直接像使用普通变量一样使用他们,由于awk的版本众多,有些内置变量并不是得到所有awk版本的支持。[A][N][P][G]表示支持该变量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk
awk同时处理多个文件
https://www.cnblogs.com/Berryxiong/p/6209332.html
awk
的数据输入有两个来源,标准输入和文件,后一种方式支持多个文件。
shell
的Pathname Expansion
方式
直接指定多个文件
那么,在多文件处理的时候,如何判断awk
目前读的是哪个文件,而依次做对应的操作呢?
当
awk
读取的文件只有两个的时候,比较常用的方法有:awk 'NR==FNR{...}NR>FNR{...}' file1 file2
awk 'NR==FNR{...}NR!=FNR{...}' file1 file2
awk 'NR==FNR{...;next}{...}' file1 file2
了解
FNR
(已读入当前文件的记录数)和NR
(已读入的总记录数)这两个awk
内置变量的意义就很容易知道这些方法是如何运作的:对于
awk 'NR==FNR{...}NR>FNR{...}' file1 file2
,读入file1的时候,已读入file1的记录数FNR一定等于awk已读入的总记录数NR,因为file1是awk读入的首个文件,故读入file1时执行前一个命令块{...}。读入file2的时候,已读入的总记录数NR一定大于读入file2的记录数FNR,故读入file2时执行后一个命令块{...}。对于
awk 'NR==FNR{...;next}{...}' file1 file2
,读入file1时,满足NR==FNR,先执行前一个命令块,但因为其中有next命令,故后一个命令块{...}是不会执行的。读入file2时,不满足NR==FNR,前一个命令块{..}不会执行,只执行后一个命令块{...}。
当
awk
处理的文件超过两个时,显然上面那种方法就不适用了。因为读第3个文件或以上时,也满足NR>FNR (NR!=FNR)
,显然无法区分开来。所以就要用到更通用的方法了:利用当前被处理参数标志:
awk 'ARGIND==1{...}ARGIND==2{...}ARGIND==3{...}...' file1 file2 file3 ...
利用命令行参数数组:
awk 'FILENAME==ARGV[1]{...}FILENAME==ARGV[2]{...}FILENAME==ARGV[3]{...}...' file1 file2 file3 ...
把文件名直接加入判断,但不通用:
awk 'FILENAME=="file1"{...}FILENAME=="file2"{...}FILENAME=="file3"{...}...' file1 file2 file3 ...
Linux下文件批量重命名
mv
命令
mv
命令rename
命令
rename
命令GNU版本:
rename old new file_list
Example:
rename "chr" "" *.gz*
perl版本:
rename 's/old/new/[g]' file_list
Example:
rename 's/chr/chrom/g' *.gz*
Bash中括号及expr
的用法
expr
的用法小括号()
()
单小括号
(...)
命令组:括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
命令替换:等同于cmd,shell扫描一遍命令行,发现了
(cmd)
结构,便将其中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。如a=$(ls)
等同于 a=`ls`用于初始化数组:如
array=(a b c d)
双小括号
((...))
整数扩展:这种扩展计算是整数型的计算,不支持浮点型。
((exp))
结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为0,或者是"False",而一个非零值的表达式所返回的退出状态码将为1,或者是"True"。若表达式是逻辑判断,为真则退出码为1,假则为0。
只要括号中的运算符、表达式符合C语言运算规则,都可用在
$((exp))
中,甚至是三目运算符。作不同进制运算时,输出结果全都自动转化成了十进制,如echo $((16#5f))
的结果为95单纯用
((x))
也可重定义变量值,如a=5; ((a++))
可将$a
重定义为6双括号中的变量可以不使用
$
符号前缀。双括号内支持多个表达式用逗号分开。
中括号[]
[]
单中括号
[...]
bash的内部命令:
[
和test
是等同的。如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。if/test
结构中的左中括号是调用test
的命令标识,右中括号是关闭条件判断的,括号两边有空格。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。test
和[]
中可用的比较运算符只有==
和!=
,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq
、-gt
这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用,对于字符串比较可以使用转义形式,如果比较"ab"和"bc":[ ab \< bc ]
,结果为真,也就是返回状态为0。[]
中的逻辑与和逻辑或使用-a
和-o
表示。
字符范围:用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。
在一个array结构的上下文中,中括号用来引用数组中每个元素的编号。
表达式计算:
count=1; echo $[${count} + 1] #result: 2
双中括号
[[...]]
[[
是bash程序语言的关键字,并不是一个命令。[[]]
结构比[]
结构更加通用。在[[
和]]
之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。支持字符串的模式匹配,使用
=~
操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]]
,结果为真。[[]]
中匹配字符串或通配符不需要引号。
使用
[[ ... ]]
条件判断结构,而不是[ ... ]
,能够防止脚本中的许多逻辑错误。如&&
、||
、<
和>
能够正常存在于[[]]
条件判断结构中,但在[]
结构中会报错。
bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。
大括号{}
{}
大括号拓展:通配(globbing)将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。
对大括号中的以逗号分割的文件列表进行拓展。如
touch {a,b}.txt
结果为a.txt b.txt
对大括号中以点点(..)分割的顺序文件列表起拓展作用,如
touch {a..d}.txt
结果为a.txt b.txt c.txt d.txt
代码块:又称内部组,这个结构事实上创建了一个匿名函数。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后一个也必须有分号。
{}
的第一个命令和左括号之间必须要有一个空格。获取变量:
${x}
或$x
示例
expr用法
expr
命令是一个手工命令行计数器,用于求表达式变量的值,一般用于整数值,也可用于字符串。运算表达式用法
运算
正则匹配,返回分组结果,每次只能设定一个分组
match用法:从开头匹配,返回字符所在下标(下标从1开始),未匹配返回0,使用通配符时返回最后一个匹配字符所在下标
字符串操作
Linux下按Tab补全命令时忽略大小写
执行vim ~/.inputrc
,添加如下内容,保存重启终端后即可。
Linux tar
命令
tar
命令Linux tar(英文全拼:tape archive )命令用来建立、还原备份文件,它可以加入、解开备份文件内的文件。
语法
参数
示例
压缩文件:
tar -czvf test.tar.gz 1.txt #压缩1.txt文件为test.tar.gz
列出压缩文件内容:
tar -tzvf test.tar.gz
解压文件:
tar -xzvf test.tar.gz
排除目录中的某些文件,然后进行压缩:
tar --exclude=folder/*.txt -czvf test.tgz folder
Bash脚本传递参数
位置参数
通过在命令行的位置,来表示传入对应脚本的参数。这是最简单的一种,如下我们将4个参数对应START, END, SCFID 和 GENE 进行传入参数。
这时在执行的时候,只需在命令行输入对应参数即可,参数之间使用空格分割。
这种方法虽然简单,但是输入参数的时候必须严格对应,不能空缺参数,不能颠倒位置,这对脚本的新用户是十分不友好的。
参数处理
$#
: 传递到脚本的参数个数$*
: 以一个单字符串显示所有向脚本传递的参数。如执行"$*"
,以"$1 $2 … $n"
的形式输出所有参数。$$
: 脚本运行的当前进程ID号$!
: 后台运行的最后一个进程的ID号$@
: 在引号中返回每个参数。如执行"$@"
,以"$1" "$2" … "$n"
的形式输出所有参数。注:
$*
与$@
,相同点都是引用所有参数,不同点只有在双引号中体现出来。假设在脚本运行时写了三个参数1、2、3
,则"$*"
等价于"1 2 3"
(传递了一个参数),而"$@"
等价于"1" "2" "3"
(传递了三个参数)。$-
: 显示Shell使用的当前选项,与set
命令功能相同。$?
: 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
参数名匹配
另一种传递参数的方式就是使用关键词,通过关键词匹配进行参数传递,这种情况下的参数传入方式就比较灵活了,不依赖于参数位置。
这时在命令行,可以不按照顺序输入参数,也可以使用双横线和全称的方式输入:
当然,如果命令参数没有找到匹配,会提示错误:
这种参数传入的方式有两个关键,一个是使用case
语句,另一个是使用了shift
。shift
的作用主要是移动位置参数。每执行一次都讲第一个位置参数向右移动一次。当然,如果是shift n
就是每执行一次,向右移动n个位置。参考:https://www.computerhope.com/unix/bash/shift.htm
有时候我们常使用等号=
来进行参数传递,整体做法和使用上述空格是一样的。
Linux echo
不换行输出的两种方式
echo
不换行输出的两种方式方法一:
echo -n text
方法二:
echo -e "text\c"
echo -e
可以处理特殊字符,其后可接的特殊字符有:
Linux下批量中止多个进程
Linux下split
命令将一个大文件按行拆分成小文件
split
命令将一个大文件按行拆分成小文件sed正则表达式匹配,各种括号的转义和不转义
[ ] 需要匹配的时候,需要转义
( ) 需要匹配的时候,不要转义
{ } 需要匹配的时候,不要转义
当需要匹配数字,字母等使用中括号时候,不要转义;但使用大括号作为特殊字符时(表示前面的字符出现的次数),需要转义
当需要适配符,需要使用
\1
来替换正则表达式的对应参数时,不能写(regrexxxx)
,而要写\(regrexxxx\)
;后面回溯引用写\1
在做为特别字符时候
+
必须转义为\+
才有效,而*
则不需要
Sed正则表达式详细介绍
详见此文
行开始 ^
^
行尾 $
$
单个字符 .
.
匹配除行字符结尾的任何单个字符
匹配字符集合 []
[]
匹配这些字符,仅占一个位置
不匹配字符集 [^]
[^]
字符范围 [-]
[-]
零到一次出现 \?
\?
匹配零次或一次其前面的字符
一次或多次出现 \+
\+
匹配一次或多次其前面的字符
零或多次出现 *
*
匹配零次或多次其前面的字符
n个重复 \{n\}
\{n\}
共出现n个其前面的字符
最少出现n个 \{n,\}
\{n,\}
最少出现n个其前面的字符
m到n次出现 \{m, n\}
\{m, n\}
或 \|
\(\|\)
\|
\(\|\)
awk中的回溯引用 (back references)
详见此文
The usual (and correct) answer for backreferences in awk
is: "you can't do backreferences in awk
". That is only partly true.
If you need to match a pattern using a regular expression with backreferences, like what you do in sed
:
or similar things, then well, you can't do that easily with awk
.
But if you are using backreferences during string substitution, to insert text previously captured by a capture group, then you will almost certainly be able to get what you want with awk
. Following are some hints:
First and easiest answer (requires GNU
awk
): usegensub()
. It supports backreferences natively. Example:
Note that gensub()
, unlike sub()
and gsub()
, returns the modified string without touching the original. Also note that the third parameter is much like sed
's match number specification in the s/pattern/replacement/
command: it can either be a number, indicating to replace only that specific match, or the string "g" (as in the example), to indicate replacement of all matches. See the gawk
manual for more information (including why backslashes must be escaped in the replacement text).
Second answer: sometimes you don't really need backreferences, since what you want can be accomplished without. Examples:
Both things can be done in awk
(and sed
as well!) without the need of backreferences. You just delete the part of the line you don't need:
Generally speaking, however, the above methods (both sed
and awk
) require that you have only one matching substring to extract per line. For the same purpose, with some awks (see AwkFeatureComparison), you can use the possibility to assign a regexp to RS to "pull out" substrings from the input (and without the limitation of at most one match per line). See the last part of Pulling out things for more information and examples.
Third answer: see GeneralizedTextReplacement for a detailed discussion of a framework for generalized text replacement, including an explanation on how to emulate backreferences (and much more) with
awk
.
Linux两个文件求交集、并集、差集
定义
交集:两个文件中都出现的行
并集:两个文件中的所有行加起来,去掉重复
差集:在一个文件中存在,而在另一个文件中不存在
方法一:sort
+uniq
sort
+uniq
交集:
sort a.txt b.txt | uniq -d
(用sort将a.txt b.txt文件进行排序,uniq使得两个文件中的行唯一,使用-d输出两个文件中次数大于1的内容,即是得到交集)并集:
sort a.txt b.txt | uniq
(将a.txt b.txt文件进行排序,uniq使得两个文件中的内容为唯一的,即可得到两个文件的并集)差集:
a.txt-b.txt:
sort a.txt b.txt b.txt | uniq -u
(将两个文件排序,最后输出a.txt b.txt b.txt文件中只出现过一次的内容,因为有两个b.txt所以只会输出只在a.txt出现过一次的内容,即是a.txt-b.txt差集)b.txt-a.txt:
sort b.txt a.txt a.txt | uniq -u
uniq
参数说明:-d
仅显示重复出现的行列-u
仅显示出一次的行列
方法二:comm
,用于比较两个已排过序的文件
comm
,用于比较两个已排过序的文件交集:
comm -12 a.txt b.txt
差集:
a.txt-b.txt:
comm -23 a.txt b.txt
b.txt-a.txt:
comm -13 a.txt b.txt
注: a.txt b.txt两个文件需要先分别排序;
comm
默认输出为三列,第一列为是A-B,第二列B-A,第三列为A交Bcomm
参数说明:-1
不显示只在第1个文件里出现过的列-2
不显示只在第2个文件里出现过的列-3
不显示只在第1和第2个文件里出现过的列。
方法三:grep
grep
交集:
grep -F -f a.txt b.txt
差集:
a.txt-b.txt:
grep -F -v -f b.txt a.txt
b.txt-a.txt:
grep -F -v -f a.txt b.txt
注: grep求交集不要求输入文件是排序的,但最好是唯一的;差集时注意输入文件的顺序
grep
参数说明:-F
将样式视为固定字符串的列表-f
指定规则文件,其内容含有一个或多个规则样式,查找符合规则条件的文件内容,格式为每行一个规则样式-v
显示不包含匹配文本的所有行
方法四:awk
awk
交集:
awk 'NR==FNR{ a[$1]=a[$1]+1} NR>FNR{ if(a[$1]>=1 &&b[$1]<1){ print $1;b[$1]=b[$1]+1}}' a.txt b.txt
差集:
a.txt-b.txt:
awk 'NR==FNR{a[$1]=$1} NR>FNR{if(a[$1] == ""){print $1}}' b.txt a.txt
b.txt-a.txt:
awk 'NR==FNR{a[$1]=$1} NR>FNR{if(a[$1] == ""){print $1}}' a.txt b.txt
当NR(表示已经处理的行数)==FNR(表示当前文件处理的行数)时,处理的是a.txt,NR>FNR时,处理的是b.txt,在处理a.txt时,把a数组记录不同字符串个数,且起到去重作用。在处理b.txt时,判断a数组中是否含当前字符串,并且在本文件中出现的次数小于1,同样也是起到了去重的作用。
perl
sed
awk
grep
等对正则表达式的支持的差别
perl
sed
awk
grep
等对正则表达式的支持的差别以perl的正则为基准,不同的用法以粉红色标出。
grep 2.5.1
egrep 2.5.1
sed 3.02 sed 4.07
awk 3.1.1
perl 5.8.0
vim 6.1
JavaScript ??
转义
\
\
\
\
\
\
\
行头
^
^
^
^
^
^
^
行尾
$
$
$
$
$
$
$
n个 {n} {m,n} {m,} {,n}
\{n\}
{n}
\{n\}
{n}或\{n\} 仅定义 --posix 或 --re-interval有效(要表达}和{,得用\\{和\\} 没有定义--posix或--re-interval时,不能用{n}的语法, \}\{和}{同义
{n}
\{n\}
{n}
{0,}
*
*
*
*或\*, (要表达*,得用\\*)
*
*
*
{1,}
\+
+
\+
+或\+, (要表达+, 得用\\+)
+
\+
+
{0,1}
\?
?
\?
?或\?, (要表达?, 得用\\?)
?
\?
?
任意字符
.
.
.
. 含\n.
. /s修饰后则含
. 除
. 除
(pat) 匹配并获结果
(pat)
(pat)
(pat)
(?:pat) 匹配但不获结果
不支持
不支持
不支持
不支持
(?:pat)
不支持
(?:pat)
(?=pat) 等于预查
不支持
不支持
不支持
不支持
(?=pat)
不支持
(?=pat)
(?!pat) 不等预查
不支持
不支持
不支持
不支持
(?!pat)
不支持
(?!pat)
| 或
\|
|
\|
|或\| (要表达|,得用\\|)
|
\|
|
其中任意字符
[xyz]
[xyz]
[xyz]
[xyz]
[xyz]
[xyz]
[xyz]
[.ch.] [=ch=]
不支持
不支持
[.ch.]
不支持
不支持
不支持
不支持
单词边界 \b
\b
\b
\b
不支持
\b
不支持
\b
非单词边界 \B
\B
\B
\B
不支持
\B
不支持
\B
单词左右边界 <>
\< \>
\< \>
\< \>
不支持 (><和\>\<和\\>\\<同义
不支持(><和\>\<同义
\< \>
不支持(><和\>\<同义
控制字符 /cx
不支持
不支持
\cx
不支持
\cx
不支持
\cx
数字\d
不支持
不支持
不支持
不支持
\d
\d
\d
非数字\D
不支持
不支持
不支持
不支持
\D
\D
\D
换页 \f
不支持
不支持
高版本支持
\f
\f
另义 \f表示文件名字符
\f
换行
不支持
不支持
不支持
回车
不支持
不支持
空白 \s
不支持
不支持
不支持
不支持
\s
\s
\s
非空白 \S
不支持
不支持
不支持
不支持
\S
\S
\S
制表符
不支持
不支持
高版本支持
垂直制表符 \v
不支持
不支持
高版本支持
\v
\v
另义 \v表示very magic
\v
单词字符 \w [A-Za-z0-9_]
\w
\w
\w
不支持
\w
\w
\w
非单词字符 \W [^A-Za-z0-9]
\W
\W
\W
不支持
\W
\W
\W
\xn 16进制
不支持
不支持
高版本支持
\xn
\xn
另义 \x表示[0-9A-Za-z]
\xn
\n 八进制
不支持
不支持
不支持
不支持
\n 后向引用
\n 仅取结果可用
\n 仅取结果可用
[:alnum:] 字母和数字
[:alnum:]
[:alnum:]
[:alnum:]
[:alnum:]
[:alnum:]
[:alnum:]
不支持
[:alpha:] 字母
[:alpha:]
[:alpha:]
[:alpha:]
[:alpha:]
[:alpha:]
[:alpha:]
不支持
[:cntrl:] 控制字符
[:cntrl:]
[:cntrl:]
[:cntrl:]
[:cntrl:]
[:cntrl:]
[:cntrl:]
不支持
[:digit:] 数字
[:digit:]
[:digit:]
[:digit:]
[:digit:]
[:digit:]
[:digit:]
不支持
[:graph:] 可打印字符(不含空格)
[:graph:]
[:graph:]
[:graph:]
[:graph:]
[:graph:]
[:graph:]
不支持
[:lower:] 小写
[:lower:]
[:lower:]
[:lower:]
[:lower:]
[:lower:]
[:lower:]
不支持
[:print:] 可打印字符(含空格)
[:print:]
[:print:]
[:print:]
[:print:]
[:print:]
[:print:]
不支持
[:punct:] 标点
[:punct:]
[:punct:]
[:punct:]
[:punct:]
[:punct:]
[:punct:]
不支持
[:space:] 空格
[:space:]
[:space:]
[:space:]
[:space:]
[:space:]
[:space:]
不支持
[:upper:] 大写字母
[:upper:]
[:upper:]
[:upper:]
[:upper:]
[:upper:]
[:upper:]
不支持
[:xdigit:] 16进制数字
[:xdigit:]
[:xdigit:]
[:xdigit:]
[:xdigit:]
[:xdigit:]
[:xdigit:]
不支持
[:return:]
不支持
不支持
不支持
不支持
不支持
[:return:]
不支持
[:tab:]
不支持
不支持
不支持
不支持
不支持
[:tab:]
不支持
[:escape:]
不支持
不支持
不支持
不支持
不支持
[:escape:]
不支持
[:backspace:]
不支持
不支持
不支持
不支持
不支持
[:backspace:]
不支持
使用Xshell登录Linux子系统 (WSL)
习惯用Linux
系统的用户,一般喜欢使用xshell
通过SSH
登录Linux
系统,然后在界面优美的命令端操作Linux
命令。以下来介绍如何完美使用xshell
登录Windows 10
Linux
子系统:
查看
ip
配置
SSH
服务
使用
Xshell
登录
上面命令执行完之后,在xshell
中输入用户名和ip
就可以通过xshell
登录自己电脑的Linux。
配置永久解决方案
通过上面的方法,我们可以通过xshell
登录自己电脑的Linux
。但是断开之后重新开机,我们又需要重新配置SSH
。因此,我们需要配置以下命令下,一劳永逸。
配置好之后,下次开机,只需要在Linux
子系统的默认终端运行sh service.sh
命令后,关掉终端改用xshell
登录即可。
WSL重启方法
https://stackoverflow.com/questions/70567543/cant-restart-wsl2-lxssmanager-hangs-in-stopping-state-how-to-restart
以管理员权限运行Power Shell:
上述命令在有些情况下无法响应,导致LxssManager
服务卡在停止中的状态,既无法停止也无法启动。可在services.msc
里查看到该服务的状态,发现停止和启动按钮均为灰色。若如此,可用如下命令获得运行LxssManager
服务的svchost.exe
进程的PID
:
或者,可以直接在任务管理器的服务里找到LxssManager
服务对应的PID
(此时若直接结束该服务仍会无响应)。然后,在任务管理器的详细信息里找到该PID
对应的svchost.exe
进程,结束之。之后便可以正常使用启动命令或直接运行WSL窗口。
conda 创建/删除环境
消除WSL中ls
时Windows文件夹背光的方法
ls
时Windows文件夹背光的方法https://blog.csdn.net/qq_33882435/article/details/116264702
产生原因
首先,Linux中ls命令是自带配色的,对于某些文件夹是绿色背景色块,其实是一种权限提示,即777权限。绿色表示不安全,当其他人的权限高于所有者或者所属组时就会变成绿色,或者当文件权限大于系统默认给的最大权限时就会变成绿色,文件初始权限是644,如果变成777就会变绿;文件夹初始权限是755,变成777也会变绿;而且颜色和系统有关,修改配色方案或者修改ls显示的颜色都可以把绿色的报警隐藏掉。
这种配色提醒会导致一个问题:linux目录修改为777后,在secureCRT或者mobaxterm中就看不清楚了,背光晃眼,逼死强迫症。
当然,WSL中挂接的Windows下的文件全部默认是777权限的,所以,可想而知,ls时所有的文件夹都是带有背光的。
解决方法
不显示配色
自定义ls
命令为ls --color=none
不过这样也会让我们精心设计的配色方案全都失去意义,所以应该不是个治本方法。
对于777的文件夹不显示背景色
在终端中输入:dircolors >> ~/.bashrc
Linux系统中是使用LS_COLORS
环境变量负责运行ls
命令时看到的颜色。这个dircolors
命令会把LS_COLORS
的值重定向到.bashrc
文件之中。
LS_COLORS
键值对以冒号(:
)分隔。这些键大部分是预定义的。仅颜色值会更改。该值具有2个或多个用分号(;
)分隔的部分。
例如,di = 0 ; 34,这里di意味着颜色应该应用于目录。0表示它是正常大小,而34表示颜色是绿色。如果要为目录使用绿色粗体 ,则颜色代码应为di = 1 ; 34。此处1表示粗体。如果您还想指定背景色,则也可以为其附加代码。例如,如果要在红色背景上使用黄色普通字体,则代码应为di = 1 ; 33 ; 41
可以看到,这里的ow=34;42,34=蓝色,42=绿色背景。我们想要把绿色背景删掉,就改成ow=1;34,然后重新载入bash设置,就可以去掉ls
的背光了,并显示与普通文件夹一样的蓝色加粗字体。
附加材料
有的人可能想要改一下ls
的字体或者颜色,可以参考下面的设置:
31 = 红色 40 = 黑色背景 0 =默认颜色
32 = 绿色 41 = 红色背景 1 =粗体
33 = 橙色 42 = 绿色背景 4 =下划线
34 = 蓝色 43 = 橙色背景 5 =闪烁文字
35 = 紫色 44 = 蓝色背景 7 =反向字段(交换前景色和背景色)
36 = 青色 45 = 紫色背景 8 =隐藏(不可见)
37 = 灰色 46 = 青色背景 0 =默认颜色
90 = 深灰色 47 = 灰色背景 1 =粗体
附:LS_COLORS
的妙用
LS_COLORS
的妙用https://blog.csdn.net/u010119335/article/details/17398595 http://linux-sxs.org/housekeeping/lscolors.html
Here is an easy way to set different colours for different kinds of files when using the ls command.
Add the following lines to the bottom of your ~/.bashrc
file:
The first line makes ls
use the --color
parameter by default, which tells ls to display files in different colours based on the setting of the LS_COLORS
variable.
The second line is the tricky one, and what I have worked out so far has been by trial and error. The parameters (di
, fi
, etc.) refer to different Linux file types. I have worked them out as shown
The *.rpm=90
parameter at the end tells ls to display any files ending in .rpm
in the specified colour, in this case colour 90 (dark grey). This can be applied to any types of files (e.g. you could use *.png=35
to make jpeg files appear purple) As many or as few parameters as you like can go into the LS_COLORS
variable, as long as the parameters are separated by colons.
Using trial and error (and a little bash script I wrote... my first one ever! :) I worked out all the colour codes, at least my interpretation of them
These can even be combined, so that a parameter like di=5;31;42
in your LS_COLORS
variable would make directories appear in flashing red text with a green background!
Setting LS_COLORS
does more than just make your ls listings look pretty (although it certainly does do that), it is also very helpful in identifying files while wading through a file system.
One Example:
URL Encoding
awk中printf
的用法
printf
的用法https://www.cnblogs.com/soymilk2019/p/12165545.html
printf
函数返回一个带格式的字符串给标准输出。printf
语句包括一个加引号的控制串,控制串中可能嵌有若干格式说明和修饰符。控制串后面跟一个逗号,之后是一列由逗号分隔的表达式。printf
函数根据控制串中的说明编排这些表达式的格式。与print
函数不同的是, printf
不会在行尾自动换行。因此,如果要换行,就必须在控制串中提供转义字符。每一个百分号和格式说明都必须有一个对应的变量。要打印百分号就必须在控制串中给出两个百分号。
printf
使用的转义字符
printf
使用的转义字符c
字符
s
字符串
d
十进制整数
ld
十进制长整数
u
十进制无符号整数
lu
十进制无符号长整数
x
十六进制整数
lx
十六进制长整数
o
八进制整数
lo
八进制长整数
e
用科学记数法(e 记数法)表示的浮点数
f
浮点数
g
选用e或f中较短的一种形式
printf
的修饰符
printf
的修饰符-
左对齐修饰符
#
显示8 进制整数时在前面加个0,显示16 进制整数时在前面加0x
+
显示使用d、e、f 和 g 转换的整数时,加上正负号+或-
0
用0而不是空白符来填充所显示的值
printf
的格式说明符
printf
的格式说明符%c
打印单个ASCII 字符 printf("The character is %c\n",x) 输出: The character is A
%d
打印一个十进制数 printf("The boy is %d years old\n",y) 输出:The boy is 15 years old
%e
打印数字的e 记数法形式 printf("z is %e\n",z) 打印: z is 2.3e+0 1
%f
打印一个浮点数 printf("z is %f\n", 2.3 * 2) 输出: z is 4.600000
%o
打印数字的八进制 printf("y is %o\n",y) 输出:z is 17
%s
打印一个字符串 print("The name of the culprit is %s\n",$1) 输出:The name of the culprit is Bob Smith
%x
打印数字的十六进制值 printf("y is %x\n",y) 输出:x is f
Shell管道 (pipe, |
) 注意事项
|
) 注意事项https://www.cnblogs.com/wangxin201492/p/5030983.html https://blog.csdn.net/mdx20072419/article/details/103901292
Shell管道会形成一个子Shell,在其中使用循环修改的变量不能传递到主Shell,wait也针对主Shell的后台进程
我的wait为什么不能用
shell的管道|
实际上是产生了一级子shell,也就是在(1)
中的后台进程echo $line &
是主进程子shell的后台进程。而wait
只会等待当前进程的后台进程执行完毕,所以(1)
在遇到wait语句直接退出了。
而(2)
中,通过< $file
将文件的内容标准输入到while
中,并未通过管道输入到while
中,所以echo $line &
为主shell的后台进程,wait会等待所有的后台进程完成以后退出,
Shell变量while循环内改变无法传递到循环外
shell中使用管道会生成一个子shell,在子shell中使用while、for循环的代码也是在子shell中执行的,所以在循环中的修改的变量只在子shell中有效,当循环结束时,会回到主shell,子shell中修改的变量不会影响主shell中的变量。
Shell中按指定分隔符读取文件字段
https://www.topbyte.cn/2020/04/shell-read-file-with-delimiter/
Shell数组
https://www.runoob.com/linux/linux-shell-array.html
Last updated