用Awk或Cut打印列?

时间:2010-10-15 18:48:11

标签: scripting awk unix

我正在编写一个脚本,它将文件名作为参数,在每行的开头找到一个特定的单词 - 在本例中为单词ATOM - 并打印特定列中的值。

$FILE=*.pdb *

if test $# -lt 1
then
 echo "usage: $0 Enter a .PDB filename"
 exit
fi
if test -r $FILE
then
 grep ^ATOM $FILE | awk '{ print $18 }' | awk '{ print NR $4, "\t" $38,}'
else
 echo "usage: $FILE must be readable"
 exit
fi

我无法弄清楚三个问题:

  1. 如何使用awk仅打印包含ATOM作为第一个单词的行
  2. 如何使用awk仅打印符合上述条件的行中的某些列,特别是第2-20和38-40列
  3. 如何指出这必须是pdb文件? * .pdb *

3 个答案:

答案 0 :(得分:4)

  1. 那将是

    awk '$1 == "ATOM"' $FILE
    
  2. 使用cut可以更好地完成该任务:

    grep ^ATOM $FILE | cut -c 2-20,38-40
    
  3. 如果你想确保作为脚本的第一个参数传递的文件名以.pdb结尾:首先,请不要(文件扩展名在UNIX中并不重要),其次如果必须的话,这是一种方式:

    "${1%%.pdb}" == "$1" && echo "usage:..." && exit 1
    

    这将获取第一个命令行参数($1),如果存在,则删除后缀.pdb,然后将其与原始命令行参数进行比较。如果它们匹配,则它没有后缀,因此程序打印一条用法消息并以状态代码1退出。

答案 1 :(得分:1)

与答案相反,只需一个awk命令即可完成任务。不需要grep或cut或......

if [ $# -lt 1 ];then
 echo "usage: $0 Enter a .PDB filename"
 exit
fi
FILE="$1"
case "$FILE" in
*.pdb )

if test -r $FILE
then 
 # do for 2-20 assuming whites paces as column separators
 awk '$1=="ATOM" && NF>18 { 
   printf "%s ",$2
   for(i=3;i<=19;i++){
     printf "%s ",$i
   }
   printf "%s",$20   
 }' "$FILE"
else
 echo "usage: $FILE must be readable"
 exit
fi
;;
*) exit;;
esac

答案 2 :(得分:0)

您可以在本机bash中进行所需的所有操作,而不会产生任何子流程:

#!/bin/bash

declare    key="ATOM"
declare    print_columns=( 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 38 39 40 )

[ ! -f "${1}" ] && echo "File not found." && exit
[ "${1%.pdb}" == "${1}" ] && echo "File is wrong type." && exit

while read -a columns; do
  if [ ${columns[0]} == ${key} ]; then
    printf "%s " ${key}
    for print_column in ${print_columns[@]}; do
      printf "%s " ${columns[${print_column}]}
    fi
    printf "\n"
  fi
done < ${1}