使用循环简化bashshell脚本

使用循环简化bashshell脚本,bash,awk,Bash,Awk,我想知道是否可以通过使用循环来进一步简化shell脚本 #!/bin/bash a11=`cat CONTCAR | head -5 | tail -3 | head -1 | awk '{print $1}'` a12=`cat CONTCAR | head -5 | tail -3 | head -1 | awk '{print $2}'` a13=`cat CONTCAR | head -5 | tail -3 | head -1 | awk '{print $3}'` b21=`cat

我想知道是否可以通过使用循环来进一步简化shell脚本

#!/bin/bash

a11=`cat CONTCAR | head -5 | tail -3 | head -1 | awk '{print $1}'`
a12=`cat CONTCAR | head -5 | tail -3 | head -1 | awk '{print $2}'`
a13=`cat CONTCAR | head -5 | tail -3 | head -1 | awk '{print $3}'`
b21=`cat CONTCAR | head -5 | tail -3 | head -2 | awk '{print $1}'`
b22=`cat CONTCAR | head -5 | tail -3 | head -2 | awk '{print $2}'`
b23=`cat CONTCAR | head -5 | tail -3 | head -2 | awk '{print $3}'`
c31=`cat CONTCAR | head -5 | tail -3 | head -3 | awk '{print $1}'`
c32=`cat CONTCAR | head -5 | tail -3 | head -3 | awk '{print $2}'`
c33=`cat CONTCAR | head -5 | tail -3 | head -3 | awk '{print $3}'`

若你们不想使用数组,循环是不可能的,因为变量被分配给不同的名称,你们可以简化它一点

$ read a11 a12 a13 < <(awk 'NR==3{print $1,$2,$3}' CONTCAR)     
$ read b21 b22 b23 < <(awk 'NR==4{print $1,$2,$3}' CONTCAR)        
$ read c31 c32 c33 < <(awk 'NR==5{print $1,$2,$3}' CONTCAR) 

$read a11 a12 a13<假设您的目的是只使用任何范围内的值1、2和3,其中值的最后一位是
awk
部分所需的值,而
头部所需的值的第一位是
部分所需的值-您可以尝试以下方法:

for iX in `seq -f %02g 11 33`; do
        if ((${iX:1:1} != 1)) && ((${iX:1:1} != 2)) && ((${iX:1:1} != 3)) ; then
                echo "skipping ${iX}" ; continue ;
        else  # echo "PROCESSING: ${iX}" ;
                TOEXEC="$(cat CONTCAR | head -5 | tail -3 | head -${iX:0:1} | awk '{print ${iX:1:1}}')"
        fi ;
done ;

由于您没有提供任何示例输入和预期输出,这只是一个猜测,但可能是您想要的:

$ cat file
x1 x2 x3 x4
y1 y2 y3 y4
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
$
$ cat tst.awk
NR>2 && NR<6 {
    for (i=1; i<=3; i++) {
        printf "%c%d%d=%s\n", 97+(NR-3), NR-2, i, $i
    }
}
$
$ declare $(awk -f tst.awk file)
$
$ echo "$a11"
a1
$ echo "$b22"
b2
$ echo "$c33"
c3
$cat文件
x1x2x3x4
y1 y2 y3 y4
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
$
$cat tst.awk

NR>2&&NR另一种方法:

{
    read ignored # ignore first two lines
    read ignored
    read a11 a12 a13 ignored # "ignored" is needed to keep fields 4 on from being included in a13
    read b11 b12 b13 ignored
    read c11 c12 c13 ignored
} <CONTCAR
{
读取已忽略#忽略前两行
阅读被忽略
阅读a11 a12 a13忽略#需要“忽略”以防止字段4被包含在a13中
读取b11 b12 b13被忽略
已忽略读取c11 c12 c13

}您的问题包括一些简明的、可测试的示例输入(CONTCAR的内容)和预期的输出,有人会向您展示如何更简单、无需循环。同样请阅读《哇,斯蒂芬·查泽拉斯在@EdMorton提出的上述问题中的回答是一个惊人的必读答案,非常适合这个问题。
cat-CONTCAR | head-5 | tail-3 | head-1 | awk'{print$1}
完全等同于
awk'NR==3{print$1}CONTCAR
谢谢!!它起作用了!如果变量名称相同,但索引与a11 a12 a13 a21 a22 a23 a31 a32 a33不同,那么可能会更简单?它们都是不同的名称、不同的变量。我的意思是bash数组,但同样取决于您将如何处理这些数组。其余问题:我不清楚“<