Bash - 解析和变量

时间:2012-10-05 10:30:38

标签: bash

case 4.1
Info for unit 1 starts now
info1
info2
info3
info5  - the one I want
info6
info7
Info for unit 2 starts now
info1
info2
info3
info5  - the one I want
info6
info7
endcase 4.1

2个单位的信息在文件中打印超过1000次。

我的算法如下:

while read line
do
    if line contains unit1
    then current_unit=1
    if line contains unit2
    then current_unit2

    if line contains info5
    then 
         if current_unit = 1
            then unit1_val = *the relevant info from this line*
         elif current_unit = 2 
             then unit2_val = *the relevant info from this line*

    if both unit1_val > 20 && unit2_val > 20
    then pass

短版本:拉出我需要的值,如果在某个时刻两个值都超过某个值,则测试通过。我也尝试使用Bash

来做到这一点

为清晰起见编辑: 我遇到的问题是将变量传入和传出if语句。我的解析和比较都很好,但是当我到达最后一个if时,值不存在,因为它们是if-fi的本地,它们来自(或者不来自,视情况而定)

编辑2:

    if [[ $line == *"info5"* ]]
    then
            CURRENT_UNIT=5
    fi

    if [[ $line = *"info6"* ]]
    then
            CURRENT_UNIT=6


    fi


    if [[ $line =~ "text i want" ]]
    then
            if [[ $CURRENT_UNIT -eq 5 ]]
            then
                    UNIT_5_MEM=$(awk '/Used heap/ { gsub(/M/, " "); print $4 }')
            elif [[ $CURRENT_VC -eq 6 ]]
            then    UNIT_6_MEM=$(awk '/Used heap/ { gsub(/M/, " "); print $4 }')
            fi
    fi

    if [[ $UNIT_5_MEM -gt 20 && $UNIT_6_MEM -gt 20 ]]
    then
            echo "Passed"
    fi

2 个答案:

答案 0 :(得分:2)

我认为发布问题的原因是因为while循环中设置的变量在while循环结束后似乎消失了。

这是因为当你将while循环作为管道的一部分执行时,它会在子shell中运行,当子shell退出时,父shell的环境保持不变,不受子shell中发生的任何事情的影响。

您可以通过使用重定向或流程替换而不是管道获取输入数据来解决这个问题。例如,这不起作用:

cat inputfile | while read line; do
  case "$line" in
    foo*) output=$line ;;
  esac
done
echo "output=$output"

虽然这确实有效:

while read line; do
  case "$line" in
    foo*) output=$line ;;
  esac
done < inputfile
echo "output=$output"

以下是我提出的建议:

#!/bin/bash

declare -A output

while read line; do
    case "$line" in
        *unit*)
            unit=$(awk '{print $4}' <<<"$line")
            ;;
        info5*)
            output[$unit]="$line"
            echo "FOUND: unit=$unit, line=$line" >&2
            ;;
    esac
done < inp1

echo "Output 1:"
printf "%s\n" "${output[@]}"

### Alternately:

echo "Output 2:"
for ((i=${#output[@]}; i > 0; i--)); do
    echo "unit=$i, line=${output[$i]}"
done

我得到的输出:

FOUND: unit=1, line=info5  - the one I want
FOUND: unit=2, line=info5  - the one I want
Output 1:
info5  - the one I want
info5  - the one I want
Output 2:
unit=2, line=info5  - the one I want
unit=1, line=info5  - the one I want

如果你真的想把东西存放到像UNIT_5_MEM这样的变量,我想你可以,但数组似乎更清晰。此外,在没有看到您正在处理的数据的情况下,很难知道您要使用awk尝试实现的目标,所以我将其从我的答案中删除了。

答案 1 :(得分:1)

如果您正在寻找一种简单的方法来进行文字过滤,请查看sed[awk][1]。后者能够轻松解析,并存储一些状态。

可能是这样的(目前未经测试)

#!/bin/awk
BEGIN {
    current_unit=0;
}

function check_values()
{
   if(values[1]>20 && values[2]>20) {
     print "PASS"
     exit
   }
}

/Info for unit \d starts now/ {
   current_unit=$4;
}

/info5/ {
    values[current_unit]=value;
    check_values();
}