Scripting 使用Awk或Cut打印列?
我正在编写一个脚本,该脚本将文件名作为参数,在每行的开头找到一个单词和一个特定的单词,在本例中是单词ATOM,并打印特定列中的值Scripting 使用Awk或Cut打印列?,scripting,awk,unix,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,}' els
$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
我很难找出三个问题:
awk '$1 == "ATOM"' $FILE
cut
可以更好地完成该任务:
grep ^ATOM $FILE | cut -c 2-20,38-40
.pdb
结尾:首先,请不要这样做(文件扩展名在UNIX中并不重要),其次,如果必须这样做,这里有一种方法:
"${1%%.pdb}" == "$1" && echo "usage:..." && exit 1
这将获取第一个命令行参数($1
),去掉后缀.pdb
(如果存在),然后将其与原始命令行参数进行比较。如果它们匹配,则它没有后缀,因此程序将打印一条使用消息并以状态代码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
if[$#-lt 1];然后
echo“用法:$0输入.PDB文件名”
出口
fi
FILE=“$1”
中的大小写“$FILE”
*.pdb)
如果测试-r$文件
然后
#假设空格作为列分隔符,则执行2-20
awk'$1==“原子”&&NF>18{
printf“%s”,2美元
对于(i=3;i您可以在本机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}
!/bin/bash
declare key=“ATOM”
声明打印列=(2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 19 20 38 39 40)
[!-f“${1}]”和&echo“未找到文件”。&&exit
[“${1%.pdb}”==“${1}”]&&echo“文件类型错误。”&&exit
当读a列时;做
如果[${columns[0]}=${key}];则
printf“%s”${key}
对于${print_columns[@]};do中的print_列
printf“%s”${columns[${print\u column}]}
fi
printf“\n”
fi
完成<${1}
谢谢David!我能问你为什么说“请不要”,因为参数不能仅限于.pdb文件吗?如果我需要打印的列只能是在第18-30列中有条目的类型,我应该分别对每个列使用管道吗?grep^ATOM$1 | cut-f 18-30 | cut-f 2-20,38-40@Koala:关于文件名,如果你想使用你的程序怎么办在一个名称以.txt
?或.csv
?或.bak
?结尾的文件上,或者在一个名称完全没有扩展名的文件上?仅仅因为文件名不符合某些任意约定而使程序失败,这不是一种愚蠢的做法吗?当然,这是您的程序,因此,如果您使用ant,但如果我的经验可以作为指导的话,那么最终会有一天,您会想要取消该检查。其他UNIX实用程序(例如grep
和awk
)不要检查文件名,这是有原因的。至于你问题的第二部分,关于列,我真的不明白你在问什么。问题第二部分的澄清:如果列18-30中有内容,那么输出将显示列2-20、38-40的内容。我如何过滤?管道还是if-THEN语句?N我不知道该如何设置。啊,那会更复杂。我想不出一个方法来使用cut
,但是你可能可以做一些类似awk'$1==“ATOM”&&substr($0,18,13)!~/[^[:space:]/| cut-c2-20,38-40'
(或者您可以在awk
中完成整个过程,但程序会稍微长一点)。当然,这取决于您对“内容”的定义(在本例中,我假设它表示任何非空白字符串)。