如何在键之间均匀分配值的总数

时间:2018-04-02 09:29:52

标签: bash shell awk sed scripting

如何在键之间均匀分配值的总数。

我正在尝试将值均匀分配给键。我不希望值vcn [01-05]和vcn [06-10]分别来到密钥vsn01和vsn02。相反,我想要像vcn [01,03,05,07,09]和vcn [02,04,06,08,10]分别来到密钥vsn01和vsn02。

例如

值的数量: -

vcn01
vcn02
vcn03
vcn04
vcn05
vcn06
vcn07
vcn08
vcn09
vcn10

vsn01
vsn02

所需的输出

vsn01

vcn01
vcn03
vcn05
vcn07
vcn09

vsn02

vcn02
vcn04
vcn06
vcn08
vcn10 

注意: -

  

密钥总数 - 20,即vsn [01-20]

     

总值数 - 100,即vcn [01-100]

尝试: -

#! /bin/bash


function create_vsn_vcn_lists ()
{
    pnode_cnt=$1
    vcn_cnt=$2

    declare -a vcn_lists
    for i in `seq $pnode_cnt`; do
        ${vcn_lists[${i}]}=''
    done

    for i in `seq $vcn_cnt`; do
        for j in `seq $pnode_cnt`; do
            ret=`expr ${i} % ${j}`
            if [ $ret -eq 0 ]; then
                ${vcn_lists[${j}]}="${vcn_lists[${j}]} vcn${i}"
            fi
        done
    done

    for i in `seq $pnode_cnt`; do
        echo ${vcn_lists[${j}]}
    done

}

create_vsn_vcn_lists 2 20

3 个答案:

答案 0 :(得分:1)

请参阅https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice了解一些的原因,您不应该尝试在shell中操作这样的文本。编写shell的人也为shell编写了awk来调用操作文本,所以只需使用它。

如果您的输入只是您发布的脚本(create_vsn_vcn_lists)中显示的2个数字:

$ cat tst.awk
BEGIN {
    for (keyNr=1; keyNr<=numKeys; keyNr++) {
        printf "vsn%02d\n\n", keyNr
        for (valNr=keyNr; valNr<=numVals; valNr+=numKeys) {
            printf "vcn%02d\n", valNr
        }
        print ""
    }
}

$ awk -v numKeys=2 -v numVals=10 -f tst.awk
vsn01

vcn01
vcn03
vcn05
vcn07
vcn09

vsn02

vcn02
vcn04
vcn06
vcn08
vcn10

或者如果您的输入是2个单独的文件,因为它显示在您发布的示例输入中(number of valueskeys):

$ cat tst.awk
NR==FNR {
    keys[++numKeys] = $0
    next
}
{
    keyNr = ((FNR-1) % numKeys) + 1
    vals[keyNr] = (keyNr in vals ? vals[keyNr] ORS : "") $0
}
END {
    for (keyNr=1; keyNr<=numKeys; keyNr++) {
        print keys[keyNr] ORS ORS vals[keyNr] ORS
    }
}

$ awk -f tst.awk keys values
vsn01

vcn01
vcn03
vcn05
vcn07
vcn09

vsn02

vcn02
vcn04
vcn06
vcn08
vcn10

答案 1 :(得分:0)

您能否请关注awk并告诉我这是否对您有所帮助。

awk -v count=$(wc -l < keys) 'FNR==NR{a[++i]=$0;next} {b[FNR]=$0} END{for(k=1;k<=count;k++){print b[k] ORS;for(j=k;j<=i;j+=count){print a[j]};print "********"}}' number_of_values keys

此处也添加非单线形式的解决方案。

awk -v count=$(wc -l < keys) '
FNR==NR{
  a[++i]=$0;
  next}
{
  b[FNR]=$0
}
END{
  for(k=1;k<=count;k++){
     print b[k] ORS;
  for(j=k;j<=i;j+=count){
     print a[j]};
     print "********"}
}
' number_of_values keys

说明: 此处也为代码添加说明。

awk -v count=$(wc -l < keys) '  ##Creating a variable named count whose value is the number of lines in Input_file named keys.
FNR==NR{                        ##Checking condition here if FNR==NR which will be TRUE when first Input_file is being read.
  a[++i]=$0;                    ##Creating an array named a whose index is variable i whose value is getting incremented each time with 1 and value is current line.
  next}                         ##next keyword will skip all further statements from here on wards, since we do not want to execute them now.
{
  b[FNR]=$0                     ##This statement will be executed when 2nd Input_file named keys is being read. Creating array named b whose value is $0 with index FNR.
}
END{                            ##Starting END section of awk here now.
  for(k=1;k<=count;k++){        ##Starting a for loop whose value starts from k=1 to till value of variable count.
     print b[k] ORS;            ##Printing the value of array b whose index is k and ORS whose default value is new line.
  for(j=k;j<=i;j+=count){       ##Starting a for loop here which starts from j=k to till value of variable i and increment happens with count variable increment.
     print a[j]};               ##Printing value of array a whose index is variable j.
     print "********"}          ##Printing ******** here to segregate between different output sets.
}
' number_of_values keys         ##Mentioning the Input_file names here.

答案 2 :(得分:0)

这个怎么样?

#!/bin/bash

function create_vsn_vcn_lists {
    local vsn_cnt=$1 vcn_cnt=$2 start=1 i j
    for ((i=1; i<=vsn_cnt; ++i, ++start)); do
        printf "vsn%02d\n\n" $i
        for ((j=start; j<=vcn_cnt; j+=vsn_cnt)); do
            printf "vcn%02d\n" $j
        done
        echo
    done
}

create_vsn_vcn_lists 3 10

输出:

vsn01

vcn01
vcn04
vcn07
vcn10

vsn02

vcn02
vcn05
vcn08

vsn03

vcn03
vcn06
vcn09