常规awk-轻松对数组索引进行排序,以选择的顺序输出它们

奥利维尔·杜拉克(Olivier Dulac)

[编辑:阐明了我需要awk解决方案,并且更正了我需要对'索引'进行排序(或者,以排序的方式输出),而不是模棱两可的'值'))

在awk中,我经常使用数组中的值作为索引来计算事物或在数组中存储一组值(利用awk的indexs_are_hashes机制)

例如:如果我想知道$ 2遇到了多少个不同的值,以及每个值出现的频率:

awk '
   ... several different treatments ...
   { count[$2]++ } 
   ... other treatments ...
   END { for(str in count) { 
           print "counted: " str " : " count[str] " times." 
           ... and other lines underneath, with additional infos ...
          }
       }
 '

问题是(非GNU或其他更好的版本)常规awk(和常规nawk):

  • [A]不会按照“遇到”它们的顺序输出不同的值,
  • [B]也不提供以数字或字母顺序浏览索引的简便方法

对于[A]:不太难做..只需使用另一个数组来索引“新近看到”的条目。

问题是针对[B]的:如何进行简单的排序以重新排序不同索引的显示?

(注意:我知道gnu awk对于[B]有一种“简便”的方法:https : //www.gnu.org/software/gawk/manual/html_node/Controlling-Array-Traversal.html ...但是我想要在常规awk / nawk中做类似的事情!)

(即:我需要做一个循环来输出所看到的不同索引,对它们进行排序,在旧的awk中将它们重新读取为“ something”(例如:另一个数组ordered_seen吗?),并使用该东西来显示看到的按选择的顺序排列。这需要在awk内,因为在每个索引下,我经常需要输出一段附加信息。awk之外的“排序”将对所有内容进行重新排序)

到目前为止:我发现没有“公理化”的单线(或n线?)方式可以做到这一点。

我最终得到了一条占用几行的句柄,通过排序将每个值输出到一个文件,然后重新读取排序的文件,并将每一行按顺序插入到sorted_countindexes [n ++]中,然后for(i = 0; i <= n; i ++){...输出计数[sorted_countindexes [n]] ...}

我欢迎更好/更简单/更多的“公理化”根据常规awk(或nawk)根据索引输出索引

MCVE:这是一个简单的示例:以字母顺序输出索引会非常好:

# create the 2 basic files to be parsed by the awk:
printf 'a b a a a c c d e s s s s e f s a e r r f\ng f r e d e z z c s d r\n' >fileA
printf 's f g r e d f g e z s d v f e z a d d g r f e a\ns d f e r\n'>fileB
# and the awk loop: It outputs in 'whatever order', I want in 'alphabetical order'
for f in file? ; do printf 'for file: %s: ' "$f"
  tr ' ' '\n' < "$f" | awk ' 
       { count[$0]++ } 
   END { for(str in count){ 
           printf("%s:%d ",str,count[str]) 
          }; print "" 
       } '
done
#this outputs:
for file: fileA: d:3 e:5 f:3 g:1 r:4 s:6 z:2 a:5 b:1 c:3
for file: fileB: d:5 e:5 f:5 g:3 r:3 s:3 v:1 z:2 a:2
# I'd like to have the letters outputted in alphabetical order instead!
埃德·莫顿
$ cat tst.awk
{ cnt[$0]++ }
END {
    n = sort(cnt,idxs)
    for (i=1; i<=n; i++) {
        idx = idxs[i]
        printf "%s:%d%s", idx, cnt[idx], (i<n ? OFS : ORS)
    }

}

function sort(arr, idxs, args,      i, str, cmd) {
    for (i in arr) {
        gsub(/\047/, "\047\\\047\047", i)
        str = str i ORS
    }

    cmd = "printf \047%s\047 \047" str "\047 |sort " args

    i = 0
    while ( (cmd | getline idx) > 0 ) {
        idxs[++i] = idx
    }

    close(cmd)

    return i
}

# create the 2 basic files to be parsed by the awk:
printf 'a b a a a c c d e s s s s e f s a e r r f\ng f r e d e z z c s d r\n' >fileA
printf 's f g r e d f g e z s d v f e z a d d g r f e a\ns d f e r\n'>fileB

for f in fileA fileB ; do
    printf 'for file: %s: ' "$f"
    tr ' ' '\n' < "$f" |
    awk -f tst.awk
done
for file: fileA: a:5 b:1 c:3 d:3 e:5 f:3 g:1 r:4 s:6 z:2
for file: fileB: a:2 d:5 e:5 f:5 g:3 r:3 s:3 v:1 z:2

上面的代码只是从数组索引中构建一个以换行符分隔的字符串(用适当地引用它sh),创建一个Shell脚本,将该字符串通过管道传递到sort,然后在输出中循环。如果要修改sorts的行为,只需sortsort函数调用中添加Unix参数字符串即可,例如sort(seen,"-fu")很明显,可以修改它以打印或在sort()函数中执行任何您想做的事情,而不是填充一个索引数组,以便在返回时循环返回(如果您希望这样做,则该函数具有内聚性)。

但是请注意,它将限于系统上的最大命令行长度。

\047代码中s表示's哪个shell不允许包含在-定'界的字符串或脚本中,因此,尽管我们可以'像上面那样在从文件中读取的awk脚本中直接使用它,但是如果您要使用的话命令行上的脚本,因为当awk 'script' file从命令行和文件中解释脚本时您需要使用某些脚本来代替脚本'并且\047脚本都可以工作,因此这是'-replacement的最可移植的选择

'S(\047S)存在引用str的方式,确保外壳不展开变量,有不匹配的报价等当字符串是被管道进行排序,即他们这样做:

$ echo 'foo'\''bar $(ls) $HOME' | awk '{
    str=$0; gsub(/\047/, "\047\\\047\047", str); print "str="str
    cmd="printf \047%s\047 \047" str "\047"; print "cmd="cmd
}'
str=foo'\''bar $(ls) $HOME
cmd=printf '%s' 'foo'\''bar $(ls) $HOME'

因此,我们不会得到像这样的脆弱/越野车:

$ echo 'foo'\''bar $(ls) $HOME' | awk '{
    str=$0; print "str="str
    cmd="printf \"%s\" \"" str "\""; print "cmd="cmd
}'
str=foo'bar $(ls) $HOME
cmd=printf "%s" "foo'bar $(ls) $HOME"

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

常规awk-轻松对数组索引进行排序,以选择的顺序输出它们

来自分类Dev

如何防止awk对数组进行排序?

来自分类Dev

用awk对数组中的值进行排序

来自分类Dev

按特定的用户定义顺序对数据透视表数据帧的索引进行排序

来自分类Dev

如何对PHP数组索引进行排序?

来自分类Dev

使用awk或Perl对数据进行排序

来自分类Dev

JS不对数字对象索引进行排序

来自分类Dev

常规搜索对象数组

来自分类Dev

如何按字母顺序对索引进行排序

来自分类Dev

对数组进行排序并检索排序的索引

来自分类Dev

数组索引和常规算术转换

来自分类Dev

根据Laravel 5.1中的索引进行排序或集合或数组

来自分类Dev

使用列索引进行二维数组排序

来自分类Dev

如何对PHP数组的字符串索引进行排序

来自分类Dev

根据Laravel 5.1中的索引进行排序或集合或数组

来自分类Dev

如何对xarray数据集/数据数组的索引进行排序?

来自分类Dev

按特定顺序对数组进行排序

来自分类Dev

对数组进行排序并保持顺序

来自分类Dev

按定义的顺序对数组进行排序

来自分类Dev

遍历nD数组的常规函数

来自分类Dev

灰烬对可枚举数组进行排序或将新对象添加到常规数组

来自分类Dev

MySQL中的排序顺序为0,空,常规数字

来自分类Dev

数据操作 - 添加额外的索引列并按字母顺序对索引进行排序

来自分类Dev

如何首先对具有特定国家/地区ID的mySQL数据进行排序,然后再按常规顺序排序?

来自分类Dev

控制awk数组输出

来自分类Dev

使用预定义的排序顺序对数组进行排序

来自分类Dev

为什么使用awk的数组输出顺序不正确?

来自分类Dev

外键索引还是常规列索引?

来自分类Dev

按指定的索引对数组排序,在保持字母顺序的同时对布尔值进行优先排序

Related 相关文章

  1. 1

    常规awk-轻松对数组索引进行排序,以选择的顺序输出它们

  2. 2

    如何防止awk对数组进行排序?

  3. 3

    用awk对数组中的值进行排序

  4. 4

    按特定的用户定义顺序对数据透视表数据帧的索引进行排序

  5. 5

    如何对PHP数组索引进行排序?

  6. 6

    使用awk或Perl对数据进行排序

  7. 7

    JS不对数字对象索引进行排序

  8. 8

    常规搜索对象数组

  9. 9

    如何按字母顺序对索引进行排序

  10. 10

    对数组进行排序并检索排序的索引

  11. 11

    数组索引和常规算术转换

  12. 12

    根据Laravel 5.1中的索引进行排序或集合或数组

  13. 13

    使用列索引进行二维数组排序

  14. 14

    如何对PHP数组的字符串索引进行排序

  15. 15

    根据Laravel 5.1中的索引进行排序或集合或数组

  16. 16

    如何对xarray数据集/数据数组的索引进行排序?

  17. 17

    按特定顺序对数组进行排序

  18. 18

    对数组进行排序并保持顺序

  19. 19

    按定义的顺序对数组进行排序

  20. 20

    遍历nD数组的常规函数

  21. 21

    灰烬对可枚举数组进行排序或将新对象添加到常规数组

  22. 22

    MySQL中的排序顺序为0,空,常规数字

  23. 23

    数据操作 - 添加额外的索引列并按字母顺序对索引进行排序

  24. 24

    如何首先对具有特定国家/地区ID的mySQL数据进行排序,然后再按常规顺序排序?

  25. 25

    控制awk数组输出

  26. 26

    使用预定义的排序顺序对数组进行排序

  27. 27

    为什么使用awk的数组输出顺序不正确?

  28. 28

    外键索引还是常规列索引?

  29. 29

    按指定的索引对数组排序,在保持字母顺序的同时对布尔值进行优先排序

热门标签

归档