【问题标题】:AWK / SCRIPT , return number of values from specific field in the /etc/group fileAWK / SCRIPT ,从 /etc/group 文件中的特定字段返回值的数量
【发布时间】:2022-06-10 23:11:36
【问题描述】:

我正在尝试使用 awk 编写能够为我提供这种类型输出的东西。

我正在尝试从 /etc/group 文件

Group : root    ID:0 : 2 accounts 

Group : daemon  ID:  1  : 1 account

Group : bin  ID:  2  : 1 account

我已经试过了,

#!/bin/bash    
NbrsUtil=$(cut -d ":" -f4 /etc/group | awk -F "," '{print NF}')



awk -v utils=$NbrsUtil  -F ":"  '{print "Groupe:",$1,"ID:" $3,utils," :accounts"} ' /etc/group 

这不起作用.. 我可以尝试使用“cut”来指定我想要的字段,然后我使用awk通过“|”来计算字段的数量,我得到了很好的值,但输出不好并且不适用于我的脚本。

cut -d ":" -f4 /etc/group | awk -F "," '{print NF}'
0
0
0
0
2
0
0
0
0
0
0
0
0
0
2
0

如果我在脚本中回显命令,它将显示在一行中

#!/bin/bash

NbrsUtil=$(cut -d ":" -f4 /etc/group | awk -F "," '{print NF}')
echo $NbrsUtil
awk   -F ":"  '{print "Groupe:",$1,"ID:" $3,$4," :accounts"} ' /etc/group 

-->

0 0 0 0 2 0 0 0 0 0 0 0 0 0 2 0 0 1 1 0 1 2 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 2 0 0 1 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 2 0 0 0 0
Groupe: root ID:0  :accounts
Groupe: daemon ID:1  :accounts
Groupe: bin ID:2 :accounts
Groupe: sys ID:3 :accounts
Groupe: adm ID:4 franco,root :accounts
Groupe: tty ID:5 :accounts
Groupe: disk ID:6 :accounts
Groupe: lp ID:7 :accounts
Groupe: mail ID:8 :accounts

任何帮助将不胜感激:)

【问题讨论】:

    标签: linux bash awk field script


    【解决方案1】:

    awk 有一个 split 函数可以提供帮助:

    split(s, a[, fs ])
    将字符串 s 拆分为数组元素 a[1]a[2]、...、a[n]return n[...]如果没有给出fs,则应使用ERE fs 或字段分隔符FS 进行分隔。

    所以你可以这样做:

    awk -F: '{print "Group:",$1,"ID:",$3,"Accounts:",split($4,_,",")}' /etc/group
    

    【讨论】:

    • 这解决了我的问题,谢谢,我唯一的问题是,下划线是什么意思?它只是数组的名称吗?
    • 对,就是split函数需要的数组变量名;使用_ 来表明变量/参数不用于任何事情是一种常见的做法
    • 感谢输入,不知道 awk 存在 Split 函数。有用的
    • 不客气。这是awk pubs.opengroup.org/onlinepubs/9699919799/utilities/… 中的标准“字符串函数”列表。 GNU/BSD/etc awk 有更多,但它们没有标准化,所以我倾向于不使用它们,因为我的小脚本通常适用于各种操作系统
    • 更好的是,将关于 split 的最后一部分更改为 :::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::: :::::: :::::::::::::::: gsub( / [ , ] / , " & " , $ 4 ) + 1 ::::::::(只有间距可读性的东西 - 它是相同结果的更轻量级的方法,而不会产生物理拆分数组的成本
    【解决方案2】:

    你也可以使用:

    awk -F: '{
      nr = ($4 == "") ? 0 : gsub(/,/, "", $4) + 1
      print "Groupe:",$1,"ID:",$3,"Accounts:", nr " :accounts"
    }' /etc/group
    

    RARE Kpop Manifesto建议的稍微缩短的版本:

    awk -F: '{
      nr = ( "" < $4 ) + gsub(/,/, "", $4)
      print "Groupe:",$1,"ID:",$3,"Accounts:", nr " :accounts"
    }' /etc/group
    

    $4 为空时,脚本中的nr 为零。

    如果不为空,您可以使用gsub 替换所有逗号,这将返回替换的数量。

    gsub的结果加1,不为空也不是逗号的时候,还有1个账号。

    结果如下:

    Groupe: root ID: 0 Accounts: 0 :accounts
    Groupe: daemon ID: 1 Accounts: 0 :accounts
    Groupe: bin ID: 2 Accounts: 0 :accounts
    Groupe: sys ID: 3 Accounts: 0 :accounts
    Groupe: adm ID: 4 Accounts: 2 :accounts
    Groupe: tty ID: 5 Accounts: 1 :accounts
    

    【讨论】:

    • 可能会进一步压缩它,例如 ::::::: nr = ( ""
    • @RAREKpopManifesto 感谢您的评论,这看起来很有希望。所以如果我没记错的话,用&lt;比较字符串是基于字符串的长度?
    • "
    • ….. 的 gawk 尝试进行特定于区域设置的字符串比较,或按 unicode 官方排序顺序,但直接通过按字节顺序排序。对于我自己的代码,要检查字符串的前导字节是否为 ascii,我实际上是这样做的( str
    • @RAREKpopManifesto 感谢您的详尽解释,我也会根据您的建议添加版本。
    猜你喜欢
    • 2011-07-31
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2013-02-04
    相关资源
    最近更新 更多