计算化学公社

标题: 请教bash shell在特定行&列的字符替换 [打印本页]

作者
Author:
Frank    时间: 2019-3-10 13:19
标题: 请教bash shell在特定行&列的字符替换
各位老师好, 目前我想实现以下目的:将如下xyz文件从第四行开始(i.e.,坐标部分)的第一块(i.e atomic number)中的1,6改为H,C。应该怎么用bash实现?我尝试了sed -n '4,$p' file.xyz | awk -F " " '{gsub("1","H",$1)} 1' file.xyz, 但是修改后的内容和修改前的内容都存在,而不是我想实现的in-place替换, 谢谢!

0008noc H18C8 n-octane m062x_mg3s_geom
  
0 1
  6    0.0001270000    0.7622750000    0.0000000000
  6   -0.0001270000   -0.7622750000    0.0000000000
  6    1.4005600000    1.3639510000    0.0000000000
  6   -1.4005600000   -1.3639510000    0.0000000000
  1   -0.5483350000    1.1232240000    0.8756670000
  1   -0.5483350000    1.1232240000   -0.8756670000
  1    0.5483350000   -1.1232240000    0.8756670000
  1    0.5483350000   -1.1232240000   -0.8756670000
  6    1.4005600000    2.8886130000    0.0000000000
  6   -1.4005600000   -2.8886130000    0.0000000000
  1    1.9498930000    1.0037730000   -0.8756240000
  1    1.9498930000    1.0037730000    0.8756240000
  1   -1.9498930000   -1.0037730000   -0.8756240000
  1   -1.9498930000   -1.0037730000    0.8756240000
  6    2.8071160000    3.4761310000    0.0000000000
  6   -2.8071160000   -3.4761310000    0.0000000000
  1    0.8513920000    3.2460940000    0.8749630000
  1    0.8513920000    3.2460940000   -0.8749630000
  1   -0.8513920000   -3.2460940000    0.8749630000
  1   -0.8513920000   -3.2460940000   -0.8749630000
  1    2.7884900000    4.5653920000    0.0000000000
  1   -2.7884900000   -4.5653920000    0.0000000000
  1    3.3629520000    3.1507160000   -0.8804370000
  1    3.3629520000    3.1507160000    0.8804370000
  1   -3.3629520000   -3.1507160000   -0.8804370000
  1   -3.3629520000   -3.1507160000    0.8804370000



作者
Author:
cokoy    时间: 2019-3-10 14:20
sed -r 's/^  1/  H/g' file.xyz | sed -r 's/^  6/  C/g'
作者
Author:
zsu007    时间: 2019-3-10 21:36
本帖最后由 zsu007 于 2019-3-10 21:39 编辑

楼主用cat和awk搞定,awk里的参数根据你实际输出情况自行调整。该语句还可以将xyz里的元素自行设定为相应的元素符号。
cat *.xyz| awk ' {gsub(17, "Cl", $2) ; gsub(16,"S",$2); gsub("1", "H", $2); gsub(6, "C", $2); gsub(7, "N", $2); gsub(8, "O", $2); printf "%5s %10.6f %10.6f 10.6f\n",$2,$4,$5,$6}'
作者
Author:
Mikasa    时间: 2019-3-10 21:37
本帖最后由 Mikasa 于 2019-3-10 21:39 编辑

sed -i 's/ 1  / H  /' *.xyz
sed -i 's/ 6  / C  /' *.xyz
亲测可用,这个sed -i '/old/new/是用new替换文中的指定的old字符。
看你的文件里原子序号1和6前有一个空格、后有若干空格,而其它地没有这种数字加前后若干空格的情况,所以可以把‘ 1  ’和‘ 6  ’分别替换为‘ H  '和‘ C  ’。
作者
Author:
zsu007    时间: 2019-3-10 21:40
Mikasa 发表于 2019-3-10 21:37
sed -i 's/ 1 / H /' *.xyz
sed -i 's/ 6 / C /' *.xyz
亲测可用,这个sed -i '/old/new/是用new替换文中 ...

两句可以合并为一句 sed -i -e 's/ 1 / H /g; s/ 6 / C /g' *.xyz
作者
Author:
granvia    时间: 2019-3-10 21:50
zsu007 发表于 2019-3-10 21:40
两句可以合并为一句 sed -i -e 's/ 1 / H /g; s/ 6 / C /g' *.xyz

最好把g去掉
作者
Author:
granvia    时间: 2019-3-10 22:00
本帖最后由 granvia 于 2019-3-10 22:03 编辑
  1. sed 's/^ *1 / H /; s/^ *6 / C /' file.xyz
复制代码

1和6前面有无空格都适用


作者
Author:
abdoman    时间: 2019-3-11 09:37
本帖最后由 abdoman 于 2019-3-11 10:04 编辑

xyz格式第一行应该是数字(表示原子数目),如果里面有数字1,会不会被错误的替换? 或者刚刚好100多个原子。

awk '{if(NF==4) {if($1==1) {print  "H ", $2, $3, $4} else {if($1==6) {print "C ",$2,$3,$4}}} else {print $0}} '  file.xyz

或者用printf 带格式 ,比较好看 。

作者
Author:
Frank    时间: 2019-3-11 12:59
谢谢各位,受益匪浅
作者
Author:
laoman    时间: 2019-3-12 02:07
这个目的和我之前想提取高斯log文件里坐标到PDB文件类似,贴个我自己用脚本,献丑了:

  1. #!/bin/bash
  2. input=$1

  3. #abc=$(sed -n "/Stationary/, /Population/"p $input | grep -A 100 Coordinates | sed -n "/\-\-/, /\-\-\-/"p | sed /\-\-\-/d)
  4. line=$(grep -n Coordinates $input | tail -1 | cut -f1 -d":") # line number of last step's coordinates
  5. abc=$(sed -n "${line},/Link/"p $input | sed '/[a-z]/d; /[A-Z]/d; /\-\-\-/d; /\=\=\=/d')
  6. xyz=$(echo -e "$abc" | awk '{for (i=1; i<=NR; i++); \
  7. if ($2=="1") $2="H"; \
  8. if ($2=="6") $2="C"; \
  9. if ($2=="7") $2="N"; \
  10. if ($2=="8") $2="O"; \
  11. if ($2=="16") $2="S"; \
  12. if ($2=="26") $2="Fe"}; \
  13. {printf " %-2s           %12.6f%12.6f%12.6f\n", $2,$4,$5,$6}')  # add more elements if it exists

  14. echo -e "$xyz" > temp_file
  15. line=$(cat temp_file | wc -l)
  16. for i in $(seq 1 $line)
  17. do
  18.    atom_name=$(sed -n ${i}p temp_file | awk '{print $1}')
  19.    XYZ=$(sed -n ${i}p temp_file | awk '{print $2,$3,$4}')
  20.    if [ $atom_name = 'Fe' ]
  21.    then
  22.       FE='FE'
  23.       echo -e "HETATM ${i} $FE UNK 1 $XYZ 0 0 $atom_name" |\
  24.       awk '{printf "%-6s%5d %-5s%-4s%5d%12.3f%8.3f%8.3f%6.2f%6.2f%12s\n", $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12}'
  25.    else
  26.       echo -e "HETATM ${i} $atom_name UNK 1 $XYZ 0 0 $atom_name" |\
  27.       awk '{printf "%-6s%5d  %-4s%-4s%5d%12.3f%8.3f%8.3f%6.2f%6.2f%12s\n", $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12}'
  28.    fi
  29. done
复制代码





欢迎光临 计算化学公社 (http://bbs.keinsci.com/) Powered by Discuz! X3.3