Bash 通过Shell脚本分析控制表

Bash 通过Shell脚本分析控制表,bash,shell,awk,cut,Bash,Shell,Awk,Cut,一个shell脚本正在分析一个控制表,以便为它的处理获取正确的参数。 目前,它很简单-使用grep,它指向正确的行,awk{print$n}确定正确的列。 列仅由空格分隔。没有特殊的规则,只有用空格分隔的值。 一切正常,工作正常,用户喜欢。 只要没有一列是空的。对于最后一列,可以将其留空,但如果有人不在中间填写一列,则会混淆awk{print$n}逻辑。 当然,您可以作为用户来填写每个条目,也可以将列分隔符定义为“;”。 如果跳过某些内容,可以使用“;”,但我不希望更改表格样式。 所以问题是:

一个shell脚本正在分析一个控制表,以便为它的处理获取正确的参数。 目前,它很简单-使用grep,它指向正确的行,awk{print$n}确定正确的列。
列仅由空格分隔。没有特殊的规则,只有用空格分隔的值。 一切正常,工作正常,用户喜欢。
只要没有一列是空的。对于最后一列,可以将其留空,但如果有人不在中间填写一列,则会混淆awk{print$n}逻辑。 当然,您可以作为用户来填写每个条目,也可以将列分隔符定义为“;”。 如果跳过某些内容,可以使用“;”,但我不希望更改表格样式。
所以问题是:
如何有效地分析列值中有空格的表格?表如下所示:

可能会有所帮助的是: 如果列中设置了一个值,则该值在其列标题描述下(更精确,更不精确)

干杯,

Tarik

你没有说你想要的输出是什么,但这向你展示了正确的方法:

$ cat tst.awk
NR==1 {
    print
    while ( match($0,/[^[:space:]]+[[:space:]]*/) ) {
        width[++i] = RLENGTH
        $0 = substr($0,RSTART+RLENGTH)
    }
    next
}
{
    i = 0
    while ( (fld = substr($0,1,width[++i])) != "" ) {
        gsub(/^ +| +$/,"",fld)
        printf "%-*s", width[i], (fld == "" ? "[empty]" : fld)
        $0 = substr($0,width[i]+1)
    }
    print ""
}
$
$ awk -f tst.awk file
ApplikationService    ServerName    PortNumber     ControlValue_1    ControlValue_2
Read                  chavez.com    3599           john              doe
Write                 [empty]       3345           johnny            walker
Update                curiosity.org [empty]        jerry             [empty]

它使用标题行中每个字段的宽度来确定文件每一行中每个字段的宽度,然后用字符串“[empty]”替换空字段,并将每个字段左对齐,以使其更加美观。

在我看来,一个潜在的解决方案是通过各自的标题行确定列。如果端口号的列标题从第30列到第40列,脚本将在第30列到第40列中查找端口号。中的某些内容:好的,用作端口号。未找到任何内容/为空:已跳过。但考虑到我的Shell技能,我担心这项工作可能会产生负面影响:-)当然,页眉必须始终消耗与值相同或更多的空间/行,但这是可以管理的。您可以添加有关输入数据的更多详细信息吗?值是否可能超过标题定义的列,写入下一列?值也可以有空格吗?每个列的可能值是否可确定(例如,对于“端口号”列,总是
[0-9]
,对于“ControlValue\u 1/2”列,是一组已知的字符串)。请更新您的问题。我还建议更新标题,以反映您的需求,如“解析空间分隔的值,但缺少值”,Ed,非常感谢!这就是我的想法,它肯定会成功的!:-)
$ cat tst.awk
NR==1 {
    print
    while ( match($0,/[^[:space:]]+[[:space:]]*/) ) {
        width[++i] = RLENGTH
        $0 = substr($0,RSTART+RLENGTH)
    }
    next
}
{
    i = 0
    while ( (fld = substr($0,1,width[++i])) != "" ) {
        gsub(/^ +| +$/,"",fld)
        printf "%-*s", width[i], (fld == "" ? "[empty]" : fld)
        $0 = substr($0,width[i]+1)
    }
    print ""
}
$
$ awk -f tst.awk file
ApplikationService    ServerName    PortNumber     ControlValue_1    ControlValue_2
Read                  chavez.com    3599           john              doe
Write                 [empty]       3345           johnny            walker
Update                curiosity.org [empty]        jerry             [empty]