【问题标题】:how to evenly distribute total number of values between keys如何在键之间平均分配值的总数
【发布时间】:2018-09-11 12:26:13
【问题描述】:

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

我正在尝试将值平均分配给键。我不希望值 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

【问题讨论】:

  • 你的意思是你想把偶数/奇数方法分配给01和02?如果有 03、04 05 怎么办?那时我们应该得到什么输出?
  • 不是真的,以防在缩放时我有 vsn - 3 Nos 即 vsn01,vsn02,vsn03 和总值 -15 Nos 即 vcn[01-15] 然后 vsn01 - vcn01 vcn04 vcn07 vcn10 vcn13 vsn02 - vcn02 vcn05 vcn08 vcn11 vcn14 vsn03 - vcn03 vcn06 vcn09 vcn12 vcn15
  • 您为自己尝试了什么? @user3742796
  • @Inian 更新问题,答错了!
  • @user3742796,请检查我的答案一次,如果这对您有帮助,请告诉我?

标签: bash shell awk sed scripting


【解决方案1】:

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

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

$ 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

【讨论】:

    【解决方案2】:

    这个怎么样?

    #!/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
    

    【讨论】:

    • 这实际上会比等效的 awk 脚本慢几个数量级,而且跨标准 UNIX 系统的可移植性也较差,那么有什么意义呢?
    • @EdMorton 这太傻了。输出将比您的 awk 脚本慢几个数量级,那有什么意义呢?而且它可以很容易地变得更便携(例如,如果你抱怨 printfs)。
    • 不确定我是否理解。你是说你认为它不会慢几个数量级(它会 - 见why-is-using-a-shell-loop-to-process-text-considered-bad-practice)?你是说我们不应该提到有问题的代码是不可移植的,因为可以编写一些其他版本的代码可以移植?我只是在问,当等效的 awk 脚本更便携且速度更快几个数量级时,编写/使用该代码的意义何在?
    • wrt 计时 - 我刚刚做了一个快速测试,运行 1000 个 vsns 和 100000 个 vcns 你的 shell 脚本运行 time 需要 real 0m2.225s user 0m1.977s sys 0m0.246smy answer 中的第一个 awk 脚本定时需要 real 0m0.078s user 0m0.055s sys 0m0.004s,即 shell 脚本为 2.25 秒,而 awk 脚本为 0.078 秒。再说一遍——既然 awk 在每个标准 UNIX 机器上都可用,那么编写一个运行速度要慢几个数量级的非便携式 shell 脚本有什么意义?
    【解决方案3】:

    您能否尝试关注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.
    

    【讨论】:

      猜你喜欢
      • 2020-07-13
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 2019-08-01
      • 2021-12-26
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      相关资源
      最近更新 更多