Linux - 解析数据,使用什么语言

时间:2014-05-01 15:27:26

标签: linux bash parsing awk

我希望从“'”列中解析数据。基于格式。我遇到的问题我觉得自己是“黑客攻击”。用于拉取字符串和数字的bash / awk命令。如果数字/文本有不同的格式,那么脚本可能会意外失败,我会有错误。

数据:

RSSI (dBm):    -86      Tx Power:    0
RSRP (dBm):    -114     TAC:         4r5t (12341)
RSRQ (dB):     -10      Cell ID:     efefwg (4261431)
SINR (dB):      2.2

我的方法:

使用bash和awk

#!/bin/bash

DATA_OUTPUT=$(get_data)

RSSI=$(echo "${DATA_OUTPUT}" | awk '$1 == "RSSI" {print $3}')
RSRP=$(echo "${DATA_OUTPUT}" | awk '$1 == "RSRP" {print $3}')
RSRQ=$(echo "${DATA_OUTPUT}" | awk '$1 == "RSRQ" {print $3}')
SINR=$(echo "${DATA_OUTPUT}" | awk '$1 == "SINR" {print $3}')
TX_POWER=$(echo "${DATA_OUTPUT}" | awk '$4 == "Tx" {print $6}')

echo "$SINR"
echo ">$SINR<"

然而上面的输出很奇怪。

2.2   # thats fine!
<2.2  # what??? expecting >4.6<

这样的小事情让我怀疑使用awk和bash来解析数据。我应该使用C ++还是其他语言?或者有更好的方法吗?

谢谢

2 个答案:

答案 0 :(得分:1)

这应该是您的起点(如果输入数据是制表符分隔或固定宽度字段,则可以简化或删除match()):

$ cat file
RSSI (dBm):    -86      Tx Power:    0
RSRP (dBm):    -114     TAC:         4r5t (12341)
RSRQ (dB):     -10      Cell ID:     efefwg (4261431)
SINR (dB):      2.2

$ cat tst.awk
{
    tail = $0
    while ( match(tail,/[^:]+:[[:space:]]+[^[:space:]]+[[:space:]]*([^[:space:]]*$)?/) )
    {
        nvPair = substr(tail,RSTART,RLENGTH)
        sub(/ \([^)]+\):/,":",nvPair)           # remove (dB) or (dBm)
        sub(/:[[:space:]]+/,":",nvPair)         # remove spaces after :
        sub(/[[:space:]]+$/,"",nvPair)          # remove trailing spaces
        split(nvPair,tmp,/:/)
        name2value[tmp[1]] = tmp[2]             # name2value["RSSI"] = "-86"
        tail = substr(tail,RSTART+RLENGTH)
    }
}

END {
    for (name in name2value) {
        value = name2value[name]
        printf "%s=\"%s\"\n", name, value
    }
}

$ awk -f tst.awk file
Tx Power="0"
RSSI="-86"
TAC="4r5t (12341)"
Cell ID="efefwg (4261431)"
RSRP="-114"
RSRQ="-10"
SINR="2.2"

希望很明显,在match()循环之后的上述脚本中,您可以简单地说print name2value["Tx Power"]之类的内容来打印该关键短语的值。

如果您的数据是在DOS中创建的,请先在其上运行dos2unixtr -d '^M',其中^M表示文字控件-M字符。

答案 1 :(得分:0)

您的数据包含DOS样式\ r \ n行结尾。当你这样做时

echo ">$SINR<"

实际输出实际上是

>4.6\r<

回车符将光标发送回行的开头。

你可以这样做:

DATA_OUTPUT=$(get_data | sed 's/\r$//')

但是我不是一遍又一遍地解析输出,而是像这样重写:

while read -ra fields; do
    case ${fields[0]} in
        RSSI) rssi=${fields[2]};;
        RSRP) rsrp=${fields[2]};;
        RSPQ) rspq=${fields[2]};;
        SINR) sinr=${fields[2]};;
    esac
    if [[ ${fields[3]} == "Tx" ]]; then tx_power=${fields[5]}; fi
done < <(get_data | sed 's/\r$//' )