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

Bash 将Awk的输出包含到变量中并将其与整数进行比较,bash,awk,comparison,Bash,Awk,Comparison,我花了90分钟在谷歌上搜索这个问题,所以我希望我没有问一个以前被问过好几次的问题 我目前正试图解析一个日志文件,需要一行中的特定值。 文本文件内容: read: 4163419415 0 0 4163419415 0 4395.007 0 read: 4163419415 0 0 4163419415 0 4395.007 0 read: 4163419415 0 0 4

我花了90分钟在谷歌上搜索这个问题,所以我希望我没有问一个以前被问过好几次的问题

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

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
我的问题是,无论$ECREAD的值是多少,if语句总是正确的。 我试过了

[[ $ECREAD =~ ^-?[0-9]+$ ]] && echo integer
验证变量是否为整数

我还尝试通过将命令的awk部分管道化到
sed的/*$/'
sed的/^*/'
tr-d'

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

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

回答修改后的问题 假设我们有
inputfile
。我们只想检查前24行。如果其中任何一行以
read:
开头,并且最后一列大于零,则我们希望打印
Fail

如果是这样,那么:

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

  • /^read://&&$NF>0{打印“失败”}

    对于以
    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
笔记
  • /read:///code>与任何内容都不匹配。输入,至少如问题中所示,在
    read
    之间有一个空格。因此,测试更改为
    /read://

  • 代码
    {i++}o==$COUNTER'
    的用途不清楚,已将其删除

  • 样本输入中的
    ECREAD
    值是一个浮点:4395.007。shell只执行整数运算。但是,
    bc
    可以很好地处理浮动。因此,测试转换为使用
    bc


  • 与shell测试命令比较时,
    [
    ,符号
    赋值行有点乱:

    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
    进行比较(因为
    计数器
    是一个未设置的变量,因此计算结果为0)。由于条件为非真,因此不会执行打印。这可能会达到您的目的:

    ECREAD=$(awk '/^read :/ { print $8; exit}' ./txt.file)
    
    您的shell“
    if
    ”语句非常混乱:

    应该是:

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


    你可以试试类似的东西

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

    在这里,纯bash解决方案与使用
    awk
    read
    解析文件一样简单,它能够读取
    空格
    选项卡
    换行符
    分隔文本(默认值:内部字段分隔符
    $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
    

    我最好的猜测是,
    COUNTER
    是一些
    bash
    变量&看看不匹配的单引号,OP的意思可能是:
    $(awk'/read:/{i++}o=='$COUNTER'{print$8;exit}./txt.file)
    @anishsane:可能是这样,但因为
    o
    未初始化(0或空字符串),并且从未设置,除非
    $COUNTER
    也为0(空字符串不起作用)。@JonathanLeffler I aplogize,但这是该行应该显示的
    ECREAD=$(awk'/read:/{I++}I='$COUNTER'{print$8;exit}./txt.file)
    未完成意外输入抱歉。@John1024感谢您的帮助,但我仍然有问题,我也为这样一个草率的问题道歉。您的假设是正确的,我错误地输入了“示例测试”部分。应该是:读:2553734844 0 0 2553734844 0 4386.350 0,这样就不需要浮点。@John1024 Comment continued在编辑时被5分钟规则击中,试图使用这些论坛。当我使用你的代码片段时,它工作得很好,但当我在计数器中添加时,我遇到了错误:整数表达式e预期我会有不止一个“读:”(~24)row所以我认为我需要计数器。所以我认为问题在于我如何实现计数器。其他用户所做的所有更正都是正确的。我已在OP中添加了更多信息。我认为我试图过于模糊和基本,有点遗漏了一些重要的细节,我道歉。请查看我修改后的答案,并告知它是否捕获了错误所有详细信息。
    ECREAD=$(awk'/read:/{i++}i='$COUNTER'{print$8;exit}./txt.file)
    我需要计数器,因为有多次迭代,我相信计数器出于某种原因导致了问题。
    ECREAD=$(awk '/read:/ {i++}  o==$COUNTER {print $8; exit}' ./txt.file)
    
    ECREAD=$(awk '/^read :/ { print $8; exit}' ./txt.file)
    
    [ if "$ECREAD" > 0 ] 
    then
    echo "fail"
    fi
    
    if [ "$ECREAD" -gt 0 ] 
    then
        echo "fail"
    fi
    
    if [[ "$ECREAD" -gt 0 ]] 
    then
        echo "fail"
    fi
    
    $ ECREAD=$(awk '$1~/read/{print $7}' input )
    $ if [ $ECREAD -gt 0 ]
    > then 
    > echo fail
    > else
    > echo pass
    > fi
    pass
    
    #!/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