shell 字符串处理

一. 字符串截取

1. 关键字(词)截取

  • # 号截取,删除左边字符,保留右边字符
var=http://www.aaa.com/123.htm
echo ${var#*//} # 从左边开始删除第一个 // 号及其左边的所有字符
# 输出为 www.aaa.com/123.htm
  • ## 号截取,删除左边字符,保留右边字符
var=http://www.aaa.com/123.htm
echo ${var##*/} # 从左边开始删除最后(最右边)一个 / 号及其左边的所有字符
# 输出123.htm
  • %号截取,删除右边字符,保留左边字符
var=http://www.aaa.com/123.htm
echo ${var%/*} # 从右边开始,删除第一个 / 号及其右边的字符
# 输出 http://www.aaa.com
  • %% 号截取,删除右边字符,保留左边字符
var=http://www.aaa.com/123.htm
echo ${var%%/*} # 从右边开始,删除最后一个(最左边) / 号及其右边的字符
# 输出 http:

2. 定位截取

  • 从左边第几个字符开始,及字符的个数
var=http://www.aaa.com/123.htm
echo ${var:0:5} # 0 表示左边第一个字符开始,5 表示字符的总个数
# 输出 http:
  • 从左边第几个字符开始,一直到结束
var=http://www.aaa.com/123.htm 
echo ${var:5} # 5 表示左边第6个字符开始,一直到结束。 
# 输出 //www.aaa.com/123.htm
  • 从右边第几个字符开始,及字符的个数
var=http://www.aaa.com/123.htm 
echo ${var:0-7:3} # 0-7 表示右边算起第七个字符开始,3 表示字符的个数
# 输出 123
  • 从右边第几个字符开始,一直到结束
var=http://www.aaa.com/123.htm
echo ${var:0-7} # 从右边第七个字符开始,一直到结束
# 输出 123.htm

二. 字符串拼接

  • 字符串与字符串的拼接
echo "111""222"
# 输出 111222
  • 字符串与变量拼接
var="aaa"
echo "111"${var}
# 输出 111aaa

echo "111${var}" 
# 输出 111aaa
  • 变量与变量拼接
a="123"
b="456"
echo $a$b
# 输出 123456

三. 参考

nohup自动退出

两次pretrain bert的时候都因为挂起了nohup task,但是跑十个小时左右就会自动退出,后面根据时间点推测是不是没有exit服务器,今天查了下,的确有此种可能,目前在服务器做了对比实验。

正确的使用办法为:

1.先回车,退出nohup的提示。(nohup command &)
2.然后执行exit正常退出当前账户。
3.然后再去连接终端。使得程序后台正常运行。

另外建议用Tmux代替nohup.

常用shell脚本

1. 启动jupyter(可配置开机自启)

#!/bin/bash
origin_status=`ps -ef | grep -w jupyter | wc -l` # grep -w must match whole words;otherwise there is a difference between script and shell window.
if [ $origin_status -eq 1 ]
then
        current_time=`date "+%Y%m%d%H%M%S"`
        nohup jupyter notebook >jupyter.log_$current_time 2>&1 &
        now_status=`ps -ef | grep -w  jupyter | wc -l`
        if [ $now_status -eq 2 ]
        then
                echo "succeed in opening jupyter notebook at $current_time!"
        else
                echo "fail to open jupyter notebook."
        fi
else
        current_run=`expr $origin_status - 1`
        echo "$current_run jupyter notebook is open."
fi
1.修改文件
sudo vim /etc/rc.local
增加一行:su ubuntu -c /home/ubuntu/open_jupyter.sh (以ubuntu用户执行)

2.ubuntu 18.04 参考 https://zhuanlan.zhihu.com/p/63507762

3.注意
3.1 脚本中的所有函数或者命令都给出绝对路径,因为开机自启脚本会以root用户来执行
比如在该脚本中
nohup /home/ubuntu/anaconda3/bin/jupyter notebook >/home/ubuntu/jupyter.log_$current_time 2>&1 &

3.2 修改~/.jupyter/jupyter_notebook_config.py
c.NotebookApp.allow_root = True
c.NotebookApp.notebook_dir = '/home/ubuntu'

2. 自动登陆服务器(需要安装expect: brew install expect)

#!/usr/bin/expect
# set timeout 10 设置响应间隔
spawn ssh hostname@host
expect '*password*'
send "host pwd\r"
interact
#!/usr/bin/expect
set is_first [lindex $argv 0] #只能这样取得输入的参数,这是第一个参数,和bash不一样
set which_model [lindex $argv 1]
set which_ckpt [lindex $argv 2]
if { $is_first  == 1 } {# if只能这么写
        spawn ssh -i ~/Downloads/gongel_new.pem ubuntu@ec2-54-224-75-110.compute-1.amazonaws.com
        #172.31.45.39
        expect "Last login"
        send "rm -rf private_bert;sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-151b9f95.efs.us-east-1.amazonaws.com:\/   ~\/efs-mount-point;git clone -b adv_mask_bert https:\/\/github.com\/gongel\/private_bert.git\r"
        expect "Username"
        send "@qq.com\r"
        expect "Password"
        send "\r"
        expect "Resolving deltas: 100%"
        send "cd private_bert;nohup bash helper_finetune_script $which_model $which_ckpt \&\r"
        expect "*nohup.out*"
        send "\rexit\r"
        interact
} else {
        spawn ssh -i ~/Downloads/gongel_new.pem ubuntu@ec2-54-224-75-110.compute-1.amazonaws.com
        expect "Last login"
        send "cd  private_bert\r"
        interact
}

3. 时间统计

# 方法一
#!/bin/bash

startTime=`date +%Y%m%d-%H:%M:%S`
startTime_s=`date +%s`

endTime=`date +%Y%m%d-%H:%M:%S`
endTime_s=`date +%s`

sumTime=$[ $endTime_s - $startTime_s ]

echo "$startTime ---> $endTime" "Total:$sumTime seconds"
# 方法二
time bash xxx.sh
# 会返回3个时间数据
# real 该命令的总耗时, 包括user和sys及io等待, 时间片切换等待等等
# user 该命令在用户模式下的CPU耗时,也就是内核外的CPU耗时,不含IO等待这些时间
# sys  该命令在内核中的CPU耗时,不含IO,时间片切换耗时.

4. 查看集群jps(这里免密)

hosts=('master' 'slave1' 'slave2')
for host in ${hosts[@]}
do
        echo "###### ${host} jps #####"
        ssh ${host} jps  # no need to run 'exit' command
done

Tmux简单使用教程

简单理解:不用挂后台,即使shell客户端关闭,命令继续执行。会话和窗口是独立的。

1.安装
# Mac
$ brew install tmux

# Ubuntu 或 Debian
$ sudo apt-get install tmux

# CentOS 或 Fedora
$ sudo yum install tmux
2.启动或退出
# 启动
tmux

# 退出
exit
3.新建会话
# 直接新建,默认编号0,1,...
tmux

# 自定义名称
tmux new -s <session-name>
4.分离对话:不同于退出,这只是分离,后面还可以继续连接
tmux detach #新建bash窗口
5.查看当前所有对话
tmux ls
6.连接对话
# 使用会话编号
$ tmux attach -t 0

# 使用会话名称
$ tmux attach -t <session-name>
7.杀死对话:等同于进入对话后然后exit
# 使用会话编号
$ tmux kill-session -t 0

# 使用会话名称
$ tmux kill-session -t <session-name>
8.切换对话:进入对话后 然后切换
# 使用会话编号
$ tmux switch -t 0

# 使用会话名称
$ tmux switch -t <session-name>

ref:Tmux 使用教程

另外get:防止iTerm/其他客户端不掉线

  • 永久:在/etc/ssh/ssh_config增加ServerAliveInterval 60(每60s向服务器发一次心跳);
  • 暂时:ssh -o ServerAliveInterval=60 hostname@host

awk 简单操作

工作总结…

#实验文本
1^I2$
3^I4$
5^I6$

1、列操作

打印第一列
(base) B00000094065z:~ gongel$ cat a | awk '{print $1}'
1
3
5
打印最后一列
(base) B00000094065z:~ gongel$ cat a | awk '{print $NF}'
2
4
6
加一列
(base) B00000094065z:~ gongel$ cat a | awk '{print $0"\ta"}'
1	2	a
3	4	a
5	6	a
加一列(按行操作,多此一举)
'''
shell脚本
cat $1 | while read line
do
    echo $line | awk '{print $0"\ta"}';
done
'''

(base) B00000094065z:~ gongel$ sh ts.sh a
1 2 a
3 4 a
5 6 a

2、行操作

NR为当前处理行
(base) B00000094065z:~ gongel$ cat a | awk '{print NR":"$0}'
1:1	2
2:3	4
3:5	6

3、统计命令(BEGIN/END)

求和
(base) B00000094065z:~ gongel$ cat a|awk '{sum+=$1} END {print "Sum = ", sum}'
Sum =  9
求平均
(base) B00000094065z:~ gongel$ cat a|awk '{sum+=$1} END {print "Average = ", sum/NR}'
Average =  3
求最大值
(base) B00000094065z:~ gongel$ cat a|awk 'BEGIN {max = 0} {if ($1>max) max=$1 fi} END {print "Max=", max}'
Max= 5

阮一峰awk 入门教程