一个学习记录的过程

1. Awk

awk 正则匹配语法:regexp[https://www.runoob.com/regexp/regexp-syntax.html]

awk BEGIN+过滤+主体{}+END 语法编写顺序

awk 'BEGIN{i = 1} !/^(#|@)/ {theta = $4 / $5; print $1 "     " theta}' Mtot.xvg > dipoles

awk 命令行与脚本实例对比

awk '!/^(#|@)/ {for (i = 2; i <= NF; ++i) {freq[i] += $i; print freq[i] "  " $i "  " i}} END {print NR; for(i in freq) printf("%8.3f\n",freq[i]/NR*2)}'
#!/usr/bin/awk -f
# awk解释器位置


BEGIN {
    T = 2;
    printf("ok\n");
}

# 正则匹配模式,必须连接在一起
!/^(#|@)/ {
    for (i = 2; i <= NF; ++i) {
        freq[i] += $i;
        #print $0;
    }
}

END {
    print NR;
    for(i in freq)
        printf("%15.3f", freq[i] / NR * T);
    printf("\n");
}

# 数组索引并非是连续的
!/^(#|@)/ {
    if(bg == 0) {bg = FNR;}
    if(NR == FNR) {
        v1[FNR] = $2;
    } else {
        v2[FNR] = $2;
    }
} 
END {
    len = length(v1);
    for (i = bg; i < len + bg; ++i) {
        printf("%12.4f%12.4f%12.4f\n", v1[i], v2[i], (v1[i]+v2[i])/2);
    }
}

# awk 文件行列转置,列转行
{
    for(i=1;i<=NF;i++) 
        a[i,NR]=$i
}
END {
    for(i=1;i<=NF;i++) {
        for(j=1;j<=NR;j++) printf("%10.4f ",a[i,j]);
        printf("\n");
        }
}

传递数组

当需要shell的数组时,把shell当成字符串输入,awk里在使用split()函数将其分解;
awk使用的是扩展的正则表达式;awk字符串函数说明
字符串函数教程
正则表达式语法

  • 在使用if语句的时候,一定要加{},就算后面只有一条语句也得加,否则不会执行。大大的教训
  • 改变$1 $2的结果时,同时也会改变$0的值,但是这时候的$0,会自作多情的给你在每列值之间添加上空格分隔符。所以当改变列值时,要么使用printf格式化输出每列值,要么就$1 $2 $3....一个个打出来
# substr 提取字符串,awk字符串索引竟然是从1开始的
awk '{atomName=substr($12,1,1) substr($3,2);print atomName}' unit.pdb > unit
# awk筛选行, gsub替换字符串
awk -v arr="$(cat unit)" '
BEGIN {
    FIELDWIDTHS="8 7 53";
    split(arr,atomName);
    i=-1;
    len=length(atomName)
}
{   if (i > len) {i -= len};
    if (NR > 2 && NR < 45723) {gsub("[^[:space:]].*$", atomName[i], $2)};
    print $1 $2 $3;
    i++;}' nvt.gro > tt.gro

# 简单的方法就可以完成,根本用不着替换字符串,方向错了
# linux适用
awk '{atomName=substr($12,1,1) substr($3,2);print atomName}' unit.pdb > unit
awk -v arr="$(cat unit)" 'BEGIN {FIELDWIDTHS="8 7 53";
split(arr,atomName);i=-1;len=length(atomName)}
{if (i > len) {i -= len} if ($1 ~ /PCA/) {printf("%s%7s%s\n",$1,atomName[i],$3)}
else {print $0} i++;}' nvt.gro > tt.gro

# linux上显示参数过多,win可以
awk '{atomName=substr($12,1,1) substr($3,2);print atomName}' pc.pdb > pc
awk -v arr="$(awk '{atomName=substr($12,1,1) substr($3,2);print atomName}' pc.pdb)" 'BEGIN {
    FIELDWIDTHS="8 7 53";
    split(arr,atomName);}
    {if ($1 ~ /PCA/) {printf("%s%7s%s\n",$1,atomName[NR-2],$3)}
    else {print $0}
    }' nvt.gro > tt.gro

统计一下下rmsd>0.2的resid

awk '{if($2>0.2||$3>0.2||$4>0.2||$5>0.2||$6>0.2) {print $0}}' rmsf.dat
# 打印数字时,第一个数字出现了bug显示为0,不知道为什么还是使用%s吧
awk '{if($2>0.2||$3>0.2||$4>0.2||$5>0.2||$6>0.2) printf("%d ",$1)}' rmsf.dat
awk '{if($2>0.2||$3>0.2||$4>0.2||$5>0.2||$6>0.2) printf("%s ",$1)}' rmsf.dat > rmsfGreater2A
# 破案了格式问题dos2unix即可,发现不正常的文件读取大概率都是这个原因
# 统计蛋白质z轴坐标最小值随时间的变化
function proMinz {
  mkdir minz
  # 2>&1 将gmx的错误输出到标准输出, 这样可以使用管道传递, 使用sed获取Protein组所在的id
  proteinIdx=$(echo 3000 | gmx trjconv -f md.xtc -s md.tpr 2>&1 | sed -n 's/^Group *\(.*\)( *Protein).*$/\1/p')
  echo $proteinIdx | gmx trjconv -f md.xtc -s md.tpr -skip 2 -o ./minz/protein.gro
  # gro文件的第一行一般都不是空格开头, 所以可以判断文件是否读取到了下一帧的第一行
  awk 'BEGIN {
    FIELDWIDTHS="36 8";
    min = 100;
  } 
  { if ($1 !~ /^ / && NR != 1) {
      print min;
      min = 100;
    }
    if ($2 ~ /[0-9]\.[0-9]{3}$/ && $2 < min) {
      min = $2;
    }
  }
  END {
    print min;
  }' ./minz/protein.gro > ./minz/minz.dat
}

4. Sed用法

详细的教程,虽然没看过但是肯定有用sed教程

3. ffmpeg

转换图片格式

ffmpeg -hide_baatomNameer -y -i $fileName.bmp -pix_fmt rgb24 -c tiff -compression_algo lzw $fileName.tif

2. Python

import matplotlib
# 使用非交互后端,加速运行速度
matplotlib.use('Agg')
conda clean -p      #删除没有用的包
conda clean -t       #tar打包
conda clean -y -a   #删除所有的安装包及cache
conda config --set changeps1 false #关闭conda的环境提示

5. Shell

  • 搞一个生成md模板的函数
  • gitbash初始化文件位置"H:\Software\PortableGit\etc\bash.bashrc"
  • mdblog filename
function mdblog {
  echo \
'---
title: '标题'
date: 2022-01-08 15:55:55
tags: [Gromacs, shell]
published: true
hideInList: false
feature: 
isTop: false
---

<!-- more -->
' > $1.md
}

5.1 tail tailf tail -f

md运行的nohup.out日志, 使用tail 或者 tail -f 查看都有大问题, 不知道为什么, 总是会默认读取所有的行
只有使用tailf 这样才比较正常, 以后就用这个了.