我有一个可用的脚本代码,但如何使此脚本代码更多 "elegant"?
I have a script code which works, but how do I make this script code more "elegant"?
一些背景。我有两个文件(A 和 B),其中包含我需要提取的数据。
对于文件 A,我只需要最后两行,如下所示:
RMM: 17 -0.221674395053E+01 0.59892E-04 0.00000E+00 31 0.259E-03
1 F= -.22167440E+01 E0= -.22167440E+01 d E =-.398708E-10 mag= 2.0000
我需要提取以下数字:
-1st Line, 2nd field (17)
-1st Line 4th field (0.59892E-04)
-2nd Line, 1st field (1)
-2nd Line, 3rd field (-.22167440E+01)
-2nd Line, 5th field (-.22167440E+01)
-2nd Line, 8th field (-.398708E-10)
-2nd Line, 10th field (2.0000)
对于文件 B,我只需要最后 11 行,如下所示:
Total CPU time used (sec): 0.364
User time (sec): 0.355
System time (sec): 0.009
Elapsed time (sec): 1.423
Maximum memory used (kb): 9896.
Average memory used (kb): 0.
Minor page faults: 2761
Major page faults: 4
Voluntary context switches: 24
我需要提取以下数字:
-1st line, 6th field (0.364)
-2nd line, 4th field (0.355)
-3rd line, 4th field (0.009)
-4th line, 4th field (1.423)
-6th line, 5th field (9896.)
-7th line, 5th field (0.)
我的输出应该是这样的:
mainfolder1[tab/space]subfolder1[tab/space][all the extracted info separated by tab]
mainfolder2[tab/space]subfolder2[tab/space][all the extracted info separated by tab]
mainfolder3[tab/space]subfolder3[tab/space][all the extracted info separated by tab]
...
mainfoldern[tab/space]subfoldern[tab/space][all the extracted info separated by tab]
现在这是我的脚本代码:
for m in ./*/; do
main=$(basename "$m")
for s in "$m"*/; do
sub=$(basename "$s")
vdata=$(tail -n2 ./$main/$sub/A | awk -F'[ =]+' NR==1'{a=;b=;next}{print s,a,,,,, }')
ctime=$(tail -n11 ./$main/$sub/B |head -n1|awk '{print }')
utime=$(tail -n10 ./$main/$sub/B |head -n1|awk '{print }')
stime=$(tail -n9 ./$main/$sub/B |head -n1|awk '{print }')
etime=$(tail -n8 ./$main/$sub/B |head -n1|awk '{print }')
maxmem=$(tail -n6 ./$main/$sub/B |head -n1|awk '{print }')
avemem=$(tail -n5 ./$main/$sub/B |head -n1|awk '{print }')
c=$(echo $sub| cut -c 2-)
echo "$m $c $vdata $ctime $utime $stime $etime $maxmem $avemem"
done
done > output
现在,第四行 vdata 部分实际上是上一个论坛问题中的 "recycled" 行。我不完全明白。我希望我的文件 B 代码与文件 A 的 awk 代码一样优雅。我该怎么做?谢谢! :)
对于文件 B,请尝试类似的操作:
tail -n11 B | awk -F':' '{ print }'
如果你需要保留值然后回显,你可以这样做:
array=($(tail -n11 B | awk -F':' '{ print }'))
for value in "${array[@]}"
do
echo $value
done
你应该研究 find
和 xargs
因为每次你在 shell 中写一个循环只是为了操纵文本你有错误的方法但要保持简单并保留你的原始结构,听起来你可以使用类似的东西:
for m in ./*/; do
main=$(basename "$m")
for s in "$m"*/; do
sub=$(basename "$s")
fileA="${main}/${sub}/A"
fileB="${main}/${sub}/B"
awk -v sizeA=$(wc -l < "$fileA") -v sizeB=$(wc -l < "$fileB") '
NR==FNR {
if ( FNR == (sizeA-1) ) { split([=10=],p) }
if ( FNR == sizeA ) { split([=10=],a) }
next
}
{ b[sizeB + 1 - FNR] = $NF }
END {
split(FILENAME,f,"/")
print f[1], f[2], p[2], p[4], a[1], a[3], a[5], a[8], a[10], b[11], b[10], b[9], b[8], b[6], b[5]
}
' "$fileA" "$fileB"
done
done > output
请注意,以上仅打开每个 "B" 文件 1 次,而不是 6 次。
awk 'NR==1{print } NR==2{print } NR==3{print } ...'
您可以通过以下方式稍微简化一下:
NR==2 || NR==3 || NR==4
但这似乎很难维持。或者您可以使用数组:
awk 'BEGIN{a[1]=6;a[2]=4...} NR in a{ print $a[NR]}'
但我认为你真的只是想要:
awk '{print $NF}' ORS=\t
(您不需要第 1 行的第 6 个字段。您需要最后一个字段。)
与其尝试将输出收集到仅供回显的变量中,不如添加 ORS=\t
以获得制表符分隔的输出,然后让它打印到脚本的标准输出。
一些背景。我有两个文件(A 和 B),其中包含我需要提取的数据。
对于文件 A,我只需要最后两行,如下所示:
RMM: 17 -0.221674395053E+01 0.59892E-04 0.00000E+00 31 0.259E-03
1 F= -.22167440E+01 E0= -.22167440E+01 d E =-.398708E-10 mag= 2.0000
我需要提取以下数字:
-1st Line, 2nd field (17)
-1st Line 4th field (0.59892E-04)
-2nd Line, 1st field (1)
-2nd Line, 3rd field (-.22167440E+01)
-2nd Line, 5th field (-.22167440E+01)
-2nd Line, 8th field (-.398708E-10)
-2nd Line, 10th field (2.0000)
对于文件 B,我只需要最后 11 行,如下所示:
Total CPU time used (sec): 0.364
User time (sec): 0.355
System time (sec): 0.009
Elapsed time (sec): 1.423
Maximum memory used (kb): 9896.
Average memory used (kb): 0.
Minor page faults: 2761
Major page faults: 4
Voluntary context switches: 24
我需要提取以下数字:
-1st line, 6th field (0.364)
-2nd line, 4th field (0.355)
-3rd line, 4th field (0.009)
-4th line, 4th field (1.423)
-6th line, 5th field (9896.)
-7th line, 5th field (0.)
我的输出应该是这样的:
mainfolder1[tab/space]subfolder1[tab/space][all the extracted info separated by tab]
mainfolder2[tab/space]subfolder2[tab/space][all the extracted info separated by tab]
mainfolder3[tab/space]subfolder3[tab/space][all the extracted info separated by tab]
...
mainfoldern[tab/space]subfoldern[tab/space][all the extracted info separated by tab]
现在这是我的脚本代码:
for m in ./*/; do
main=$(basename "$m")
for s in "$m"*/; do
sub=$(basename "$s")
vdata=$(tail -n2 ./$main/$sub/A | awk -F'[ =]+' NR==1'{a=;b=;next}{print s,a,,,,, }')
ctime=$(tail -n11 ./$main/$sub/B |head -n1|awk '{print }')
utime=$(tail -n10 ./$main/$sub/B |head -n1|awk '{print }')
stime=$(tail -n9 ./$main/$sub/B |head -n1|awk '{print }')
etime=$(tail -n8 ./$main/$sub/B |head -n1|awk '{print }')
maxmem=$(tail -n6 ./$main/$sub/B |head -n1|awk '{print }')
avemem=$(tail -n5 ./$main/$sub/B |head -n1|awk '{print }')
c=$(echo $sub| cut -c 2-)
echo "$m $c $vdata $ctime $utime $stime $etime $maxmem $avemem"
done
done > output
现在,第四行 vdata 部分实际上是上一个论坛问题中的 "recycled" 行。我不完全明白。我希望我的文件 B 代码与文件 A 的 awk 代码一样优雅。我该怎么做?谢谢! :)
对于文件 B,请尝试类似的操作:
tail -n11 B | awk -F':' '{ print }'
如果你需要保留值然后回显,你可以这样做:
array=($(tail -n11 B | awk -F':' '{ print }'))
for value in "${array[@]}"
do
echo $value
done
你应该研究 find
和 xargs
因为每次你在 shell 中写一个循环只是为了操纵文本你有错误的方法但要保持简单并保留你的原始结构,听起来你可以使用类似的东西:
for m in ./*/; do
main=$(basename "$m")
for s in "$m"*/; do
sub=$(basename "$s")
fileA="${main}/${sub}/A"
fileB="${main}/${sub}/B"
awk -v sizeA=$(wc -l < "$fileA") -v sizeB=$(wc -l < "$fileB") '
NR==FNR {
if ( FNR == (sizeA-1) ) { split([=10=],p) }
if ( FNR == sizeA ) { split([=10=],a) }
next
}
{ b[sizeB + 1 - FNR] = $NF }
END {
split(FILENAME,f,"/")
print f[1], f[2], p[2], p[4], a[1], a[3], a[5], a[8], a[10], b[11], b[10], b[9], b[8], b[6], b[5]
}
' "$fileA" "$fileB"
done
done > output
请注意,以上仅打开每个 "B" 文件 1 次,而不是 6 次。
awk 'NR==1{print } NR==2{print } NR==3{print } ...'
您可以通过以下方式稍微简化一下:
NR==2 || NR==3 || NR==4
但这似乎很难维持。或者您可以使用数组:
awk 'BEGIN{a[1]=6;a[2]=4...} NR in a{ print $a[NR]}'
但我认为你真的只是想要:
awk '{print $NF}' ORS=\t
(您不需要第 1 行的第 6 个字段。您需要最后一个字段。)
与其尝试将输出收集到仅供回显的变量中,不如添加 ORS=\t
以获得制表符分隔的输出,然后让它打印到脚本的标准输出。