代码之家  ›  专栏  ›  技术社区  ›  Term Grecos

在空格处从数组输出时,Bash字符串被切断

  •  0
  • Term Grecos  · 技术社区  · 2 年前

    因此,我将浏览一个日志文件,并从该日志文件中提取信息,例如设备名称、位置和日志时间。它看起来像下面这样:

    edge2.mco1-9 Jun 11:32:24 GMT %SEC_LOGIN-5-LOGIN_SUCCESS: Login Success
    

    我遇到一个问题,当我运行以下程序时:

    
    for y in ${DeviceName[@]}
    do
        echo "Device: $y"
        counter=1
        for z in ${LocationName[@]}
        do
            testing=($(grep "$y\.$z\-.*\%" hacker.txt | cut -f2 -d "-" | cut -f1 -d% | head -n 1))
            if [[ ${testing[$counter]} =~ [^0-9] ]]
            then
                echo $z
                echo $testing
            fi
            
        done
        
    done
    

    日数是唯一输出的部分。DeviceName是设备名称的数组。LocationName是位置名称的数组。这个复杂的部分是因为我只想输出位置名,如果它有来自grep的东西,因为我不想有一长串没有时间附加到它的位置。我做了一个实验,把钱存到一个银行。txt文件,它确实执行了正确的时间,但由于空格的原因,输出正确的时间似乎更麻烦。举个例子,

    9 Jun 11:32:24 GMT
    

    应该是输出。有什么办法可以解决这个问题吗? 这个 $testing 就像试图做的那样 ${testing[$counter]} , $(${testing[$counter]}) ,其他方法都不管用,给了我错误。错误是 Jun ./finder: line 113: Jun: command not found 至少给了我一天的时间。显然,空间有问题,但我不知道如何解决这个问题。

    0 回复  |  直到 2 年前
        1
  •  1
  •   markp-fuso    2 年前

    设置:

    $ cat hacker.txt
    edge2.mco1-9 Jun 11:32:24 GMT %SEC_LOGIN-5-LOGIN_SUCCESS: Login Success
    $ y=edge2
    $ z=mco1
    

    这个 grep 命令:

    $ grep "$y\.$z\-.*\%" hacker.txt | cut -f2 -d "-" | cut -f1 -d% | head -n 1                                                                    
    9 Jun 11:32:24 GMT
    

    将此加载到 testing[] 数组:

    $ testing=( $(grep "$y\.$z\-.*\%" hacker.txt | cut -f2 -d "-" | cut -f1 -d% | head -n 1) )
    $ typeset -p testing
    declare -a testing=([0]="9" [1]="Jun" [2]="11:32:24" [3]="GMT")
    

    运行测试:

    $ counter=1
    $ [[ ${testing[$counter]} =~ [^0-9] ]] && echo "success"
    success
    
    # turn on debugging to see what we're testing:
    $ set -xv                                                  # turn on debugging
    
    $ [[ ${testing[$counter]} =~ [^0-9] ]] && echo "success"
    [[ ${testing[$counter]} =~ [^0-9] ]] && echo "success"
    + [[ Jun =~ [^0-9] ]]                                      # contents of testing[1] == 'Jun'
    + echo success
    success
    
    $ set +xv                                                  # turn off debugging
    

    到现在为止,一直都还不错。

    OP已说明所需的输出应如下所示:

    9 Jun 11:32:24 GMT
    

    但是现在 echo 命令有问题:

    echo $testing                                            
    

    $testing 是一个数组;没有索引 bash 对待 $testing 与…一样 ${testing[0]} 在这种情况下,输出 9 (参见 typeset -p testing -以上);要输出数组的全部内容,OP可以使用:

    $ echo "${testing[@]}"
    9 Jun 11:32:24 GMT
    

    最终结果:OP应该能够改变 echo $testing echo "${testing[@]}" 以获得所需的输出。


    OP提到了代码复杂性(加载) 测试[] 数组,比较 testing[1] ???) 是由于只有在以下情况下才打印输出 格雷普 找到匹配项。

    我们可以通过替换 for z 循环使用:

        # no need for array, just capture datetime stamp:
    
        dtstamp=$(grep "$y\.$z\-.*\%" hacker.txt | cut -f2 -d "-" | cut -f1 -d% | head -n 1)
    
        # is length of 'dtstamp' non-zero?
    
        if [[ -n "${dtstamp}" ]]
        then
            echo "${z}"
            echo "${dtstamp}"
        fi
    

    如果目标是只打印 ${z} 什么时候 格雷普 找到匹配项(即OP不需要打印) ${dtstamp} )我们可以将代码简化一点,使 为了z 循环是:

    grep "$y\.$z\-.*\%" hacker.txt >/dev/null && echo "${z}"
    

    演示:

    $ z=mco1
    $ grep "$y\.$z\-.*\%" hacker.txt >/dev/null && echo "${z}"
    mco1
    
    $ z=xxxx
    $ grep "$y\.$z\-.*\%" hacker.txt >/dev/null && echo "${z}"
                  <<<=== no output
    

    笔记:

    • 也可以移除 counter=1 根据当前代码
    • OP应该考虑剪切粘贴他们的代码(以及适当的shebang,例如, #!/bin/bash )进入 shellcheck.net ; 本文将报告语法问题,并就“最佳实践”提出一些建议