0

我有一个问题,当一个数字在某些输出之前只应该打印一次时,它会打印两次。我将突出显示最相关的内容,但为了提供上下文,我将提供我的整个脚本。

#!/bin/bash

我将 a 的输出加载ps aux到数组中。

N=0
for i in $(ps aux | awk '{print $11,$4}' | grep -v 0.0 | grep -v MEM | sort) ; do

array[$N]="$i"

let "N= $N + 1"
done

这里我把数组分成两个数组

N=0

for i in `seq 0 ${#array[@]}`; do

if [ $(( $i % 2 )) -eq 0 ]; then arrayb[$N]=${array[$i]} ; else arrayc[$N]=${array[$i]} ;fi

let "N= $N + 1"

done

现在我希望合并重复的条目(请原谅一些令人费解的变量命名;我在黑暗中拍摄试图排除故障)。

N=0
c=0

for i in `seq 0 ${#arrayb[@]}`; do

let "B= $N - 1"

A=`echo ${arrayb[$B]} | tr -d '\n'`
B=`echo ${arrayb[$N]} | tr -d '\n'`

#A=${arrayb[$B]}
#B=${arrayb[$N]}

这是我检查前一个数组元素是否等于后者的地方。如果是这样,合并并删除。

#if [ "$A" = "$B" ]; then 
#arrayc[$N]=$(bc <<< ${arrayc[$N]}+${arrayc[$B]}); unset arrayb[$B];unset arrayc[$B]; echo trololo
#echo derp
#fi

重要的部分是这个。echo $c然后我echo $A $B。但是,我的输出显示以下内容:

0
 awk
1
awk 
2
 -bash
3
-bash 
4
 -bash

什么时候应该是这样的:

0
 awk
awk 
2
 -bash
-bash 
3

echo $c
echo -n "$A" "$B"

echo ""
let "c=$c+1"


let "N= $N + 1"
done

我无法理解的是它是如何打印的,a然后是相同的循环。任何帮助将不胜感激。cbc

4

1 回答 1

1

第一个for循环可以简化为:

array=( $(ps aux | awk '$4 != 0.0 && $4 !~ /MEM/ {print $11,$4}' | sort) )

当编写为单个片段时,第二个循环是:

N=0
for i in `seq 0 ${#array[@]}`
do
    if [ $(( $i % 2 )) -eq 0 ]
    then arrayb[$N]=${array[$i]}
    else arrayc[$N]=${array[$i]}
    fi
    ((N++))
done

您每次迭代都会增加 N ,因此您arrayb[0]包含一个名称并arrayc[1]包含相应的内存使用情况。您可能应该使用:

for i in `seq 0 ${#array[@]}`
do
    if [ $(( $i % 2 )) -eq 0 ]
    then arrayb[$((i/2))]=${array[$i]}
    else arrayc[$((i/2))]=${array[$i]}
    fi
done

但是,您可能会再次将第一个分配与第二个循环结合起来做得更好:

ps aux | awk '$4 != 0.0 && $4 !~ /MEM/ {print $11,$4}' | sort |
while read name memory
do
     arrayb+=($name)
     arrayc+=($memory)
done

这里唯一的障碍是数组设置在一个退出的子shell中。幸运的是,bash提供了Process Substitution来规避这个问题:

arrayb=()
arrayc=()
while read name memory
do
     arrayb+=($name)
     arrayc+=($memory)
done < <(ps aux | awk '$4 != 0.0 && $4 !~ /MEM/ {print $11,$4}' | sort)

然后您的代码当前编写为:

N=0
c=0

for i in `seq 0 ${#arrayb[@]}`; do

    let "B= $N - 1"

    A=`echo ${arrayb[$B]} | tr -d '\n'`
    B=`echo ${arrayb[$N]} | tr -d '\n'`
    echo $c
    echo -n "$A" "$B"
    echo ""
    let "c=$c+1"
    let "N= $N + 1"

done

而且您遇到了问题,因为您访问arrayb了两次并忽略了arrayc. 您似乎还通过扭曲来撤消第二个循环的原始代码中不需要的增量。

使用反引号通常是个坏主意。改为使用$(...)tr -d '\n'应该是不必要的。echo -n "$A" "$B"紧随其后的使用echo ""很奇怪:echo "$A" "$B"就足够了吗?

for i in $(seq 0 ${#arrayb[@]})
do
    echo "${arrayb[$i]}" "${arrayc[$i]}"
done

因此,我们可以将目前提供的脚本简化为:

arrayb=()
arrayc=()
while read name memory
do
     arrayb+=($name)
     arrayc+=($memory)
done < <(ps aux | awk '$4 != 0.0 && $4 !~ /MEM/ {print $11,$4}' | sort)

for i in $(seq 0 ${#arrayb[@]})
do
    echo "${arrayb[$i]}" "${arrayc[$i]}"
done

从这里,您可以继续处理两个数组arraybarrayc,以使匹配的索引包含可比较的值。

于 2013-10-28T02:57:44.513 回答