将Awk的输出包含到变量中并将其与整数进行比较

时间:2014-11-19 03:23:16

标签: bash awk comparison

我花了最后90分钟谷歌搜索这个问题所以我希望我不会问一个之前被问过几次的问题.8

我目前正在尝试解析日志文件,并需要一行中的特定值。 文本文件内容:

read: 4163419415       0      0     4163419415   0   4395.007      0
read: 4163419415       0      0     4163419415   0   4395.007      0
read: 4163419415       0      0     4163419415   0   4395.007      1
read: 4163419415       0      0     4163419415   0   4395.007      0

我需要抓住最后一个值(可以是变量)并对其进行一些检查。

COUNTER=1
while [ $COUNTER -lt 26 ]; do
    ECREAD=$(awk '/read:/{i++}i=='$COUNTER'{print $8; exit}' ./txt.file)
    echo $ECREAD
    if [ "$ECREAD" > 0 ] 
        then
            echo "fail"
    fi
let COUNTER=COUNTER+1
done

我的问题是if语句总是为真,无论$ ECREAD是什么值。 我试过了

[[ $ECREAD =~ ^-?[0-9]+$ ]] && echo integer

验证变量是否为整数。

我还尝试通过将命令的awk部分导入sed 's/ *$//' AND sed 's/^ *//'tr -d ' '

来删除可能位于变量末尾的任何空格

我尝试将IF语句周围的[]更改为[[]] AND (( ))

我尝试将>符号更改为-gt符号。

4 个答案:

答案 0 :(得分:2)

回答修订问题

假设我们有inputfile。我们只想检查前24行。如果这些行中的任何一行以read:开头并且最后一列大于零,那么我们要打印Fail

如果是这种情况,那么:

$ awk '/^read:/ && $NF > 0 {print "Fail";} NR>=24{exit;}' inputfile
Fail

工作原理

  • /^read:/ && $NF > 0 {print "Fail";}

    对于以read:开头并且其最后一列$NF大于零的任何行,则会打印Fail

  • NR>=24{exit;}

    awk提供了一个名为NR的记录(行)计数器。处理完第24行后,程序将退出而无需进一步阅读。

使用bash循环替代

如果目标是在bash循环内一次使用awk一行,那么尝试:

for ((counter=1; counter<26; counter++))
do
    ecread=$(awk -v num=$counter '/read:/ && NR==num {print $8} NR==num{exit;}' ./txt.file)
    echo ecread=$ecread
    if [ "$ecread" ] && [ "$ecread" -gt 0 ]
    then
        echo "fail"
    fi
done

工作原理

  • for ((counter=1; counter<26; counter++)); do

    这会在计数器上启动bash循环。

  • ecread=$(awk -v num=$counter '/read:/ && NR==num {print $8} NR==num{exit;}' ./txt.file)

    这会将bash变量counter的值传递给awk作为变量num。如果行号num包含read:,则会打印字段8的值。处理行号num后,awk退出。

  • if [ "$ecread" ] && [ "$ecread" -gt 0 ]

    这会启动if - then语句。如果(a)then具有非空值,则执行ecread部分;(b)如果非空值大于零,则执行ECREAD=$(awk '/read :/{print $8; exit}' ./txt.file) echo ECREAD=$ECREAD if [ 1 = "$(echo "$ECREAD > 0" | bc)" ] then echo "fail" fi 部分。

回答原始问题

尝试:

/read:/

注释

  • read与任何内容都不匹配。输入至少在问题中显示,在:/read :/之间有一个空格。因此,测试更改为{i++}o==$COUNTER'

  • 代码ECREAD的目的不明确,已删除。

  • 示例输入中bc的值为float:4395.007。 shell只进行整数运算。但是,bc可以很好地处理浮点数。因此,测试转换为使用[

  • 在与shell测试命令>进行比较时,符号<-eq按字典顺序比较字符串值。对于数字测试,可以使用助记符为-ne-lt-le-gt-geECREAD=4395.007 fail

上面提供的示例输入代码的输出是:

read: 4163419415 0 0 4163419415 0 4395.007 0

替代解释

如果样本输入中存在错位空间,请考虑此替代方案。假设输入如下:

bc

现在,第8个字段不是浮点数而是零。在这种情况下,不需要ECREAD=$(awk '/read:/{print $8; exit}' ./txt.file) echo ECREAD=$ECREAD if [ "$ECREAD" -gt 0 ] then echo "fail" fi ,代码可以简化为:

ECREAD=0

以上代码的输出是:

{{1}}

答案 1 :(得分:0)

分配线有点混乱:

ECREAD=$(awk '/read:/{i++}o==$COUNTER'{print $8; exit}' ./txt.file)

有三个单引号,没有反斜杠,这会造成麻烦。你可能需要:

ECREAD=$(awk '/read:/ {i++}  o==$COUNTER {print $8; exit}' ./txt.file)

这在语法上是有效的。它并不清楚它是否符合您的期望。如果模式匹配(它不匹配您的样本数据),则变量i会递增,否则将不使用。测试o == $COUNTER将未设置的变量o$0进行比较(因为COUNTER是未设置的变量,因此计算结果为0)。由于条件不正确,因此不执行打印。这可能符合你的意图:

ECREAD=$(awk '/^read :/ { print $8; exit}' ./txt.file)

你的shell&#39; if&#39;声明是一大堆:

[ if "$ECREAD" > 0 ] 
then
echo "fail"
fi

它应该是:

if [ "$ECREAD" -gt 0 ] 
then
    echo "fail"
fi

或:

if [[ "$ECREAD" -gt 0 ]] 
then
    echo "fail"
fi

答案 2 :(得分:0)

您可以尝试类似

的内容
$ ECREAD=$(awk '$1~/read/{print $7}' input )
$ if [ $ECREAD -gt 0 ]
> then 
> echo fail
> else
> echo pass
> fi
pass

答案 3 :(得分:0)

这里的纯bash解决方案就像使用awk解析文件一样简单。 read能够在不更改分隔符的情况下阅读spacetabnewline分隔文本(默认:内部字段分隔符$IFS)。然后,您可以将前七个值读入垃圾变量并丢弃,只留下您感兴趣的ecread值。

awk解决方案也很好,但是如果您使用bash工作,它也可以满足您的需求而无需依赖外部流程:

#!/bin/bash

## accept filename as first argument to script (default dat/ecread.dat)
fn="${1:-dat/ecread.dat}"

## validate file is readable
[ -r "$fn" ] || {
    printf "error: file not readable '%s'. Usage: %s <filename> (dat/ecread.dat)\n\n" "$fn" "${0//*\//}"
    exit 1
}

declare -i counter=1        # declare counter as int, set to 1

## read each line in data-file and discard first 7 values (while counter < 26)
while [ "$counter" -lt 26 ] && read a a a a a a a ecread || [ -n "$ecread" ]; do

    printf " ecread: %s" "$ecread"

    ## test ecread > 0, if so fail, if not OK
    [ "$ecread" -gt 0 ] && printf " -- fail\n" || printf " -- OK\n"

    counter+=1

done <"$fn"

exit 0

<强>输出:

$ bash ecread.sh
 ecread: 0 -- OK
 ecread: 0 -- OK
 ecread: 1 -- fail
 ecread: 0 -- OK