对字符串数组

时间:2016-09-15 13:13:55

标签: linux bash macos sorting unix

我需要做的是从etc/group获取用户列表,然后对其进行排序,然后计算唯一条目。

现在我只设法获取用户名。但我怀疑这是错误的。

#!/bin/bash
usernames=();

while IFS=: read -r Groups Tmp1 Tmp2 Username
do
  if [ $Username!="" ];
  then
    usernames+=($Username);
  fi;
done < /etc/group

然后我也尝试对它进行排序,但输出非常很奇怪:

排序:

IFS=$'\n' sorted=($(sort <<<"${usernames[*]}"))
unset IFS

输出:

echo ${usernames[@]}
echo ""
echo ${sorted[@]}

结果:

root root root root root root _teamsserver root root _taskgated root root,_jabber,_postfix,_cyrus,_calendar,_dovecot _calendar,_jabber,_postfix _devicemgr,_teamsserver _eppc root _teamsserver _devicemgr _softwareupdate _locationd _teamsserver _devicemgr,_calendar,_teamsserver,_xserverdocs _teamsserver,_devicemgr _warmd

_calendar,_jabber,_postfix _devicemgr _devicemgr,_calendar,_teamsserver,_xserverdocs _devicemgr,_teamsserver _eppc _locationd _softwareupdate _taskgated _teamsserver _teamsserver _teamsserver _teamsserver,_devicemgr _warmd root root root root root root root root root root root,_jabber,_postfix,_cyrus,_calendar,_dovecot

我没有bash经验,绝对无法让它发挥作用。

我需要最基本的解决方案来从/ etc / group获取用户名的排序列表,只包含唯一的条目并打印每个用户的重复数量。

对于ex,如果我有这个/etc/group文件:

nobody:*:-2:
nogroup:*:-1:
wheel:*:0:root
daemon:*:1:root
kmem:*:2:root
sys:*:3:root
tty:*:4:root
operator:*:5:root
mail:*:6:_teamsserver

我想得到这个:

root 6
_teamsserver 1

4 个答案:

答案 0 :(得分:3)

每个用户名&#39;字段实际上是一个可选的空逗号分隔的用户名列表。要将用户名分开,您需要在逗号上拆分条目。

如果我从你的循环开始,我可能会使用:

sorted=($(while IFS=: read -r Groups Tmp1 Tmp2 Usernames
          do
              if [ -n "$Usernames" ];
              then
                  echo "$Usernames"
              fi
          done < /etc/group |
          tr ',' '\n' |
          sort -u
       ))

 echo "${sorted[@]}"

这会绕过中间usernames数组。如果您真的想要这样,那么保留原始循环并通过sort之前的tr命令将输入​​传递给sort

IFS=$'\n' sorted=($(tr ',' '\n' <<<"${usernames[*]}" | sort -u))

这将生成一个数组sorted,其中包含按排序顺序排列的唯一名称列表。

如果您想要的只是一个唯一名称的计数,我可能会在awk中完成整个事情。实际上,我很想使用awk代替while循环。

如果您想要计算每个唯一名称的出现次数,那么您可以使用sort -u代替sort | uniq -c而不是/etc/group。统计信息的选项和变体很多 - 关键是您需要在逗号上拆分tr ', ' '\n'文件的最后一个字段。如果由于某种原因你在该列表中有空格,你可能也必须摆脱它们。 awk会这样做。

使用awk -F: '{ n = split($4, a, ","); for (u = 1; u <= n; u++) count[a[u]]++i } END { for (u in count) print u, count[u] }' /etc/group ,您可以:

a

它将第四个字段拆分为数组count,然后计算count数组中每个名称的出现次数。最后,它打印root 11 _warmd 1 _locationd 1 _jabber 2 _taskgated 1 _postfix 2 _devicemgr 4 _calendar 3 _cyrus 1 _teamsserver 6 _dovecot 1 _xserverdocs 1 _eppc 1 _softwareupdate 1 数组中的条目。在我的Mac上,它产生了:

defmodule Elemental.TxChat.Room do
  use Elemental.TxChat.Web, :model

  schema "rooms" do
    field :name, :string

    # Foreign key indicating which user created this room
    # One user can create any number of rooms 
    belongs_to :created_by, Elemental.TxChat.User
    field :created_from_app, :integer

    many_to_many :members, Elemental.TxChat.User, join_through: "rooms_users"

    timestamps()
  end

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:name, :created_by, :created_from_app])
    |> validate_required([:name, :created_by, :created_from_app])
  end
end

您可以根据需要进一步对其进行排序。

答案 1 :(得分:2)

你可以尝试类似的东西:

ngSubmitFunction()

awk -F ':' '{ if(length($4)) { gsub(",", "\n", $4); print $4 } }' /etc/group | \ sort | uniq -c 命令获取所有非空的第4个字段(':'作为分隔符)并将',替换为'\ n'以防一个组有多个用户。

然后我们对独特的外观进行排序和计数。

编辑:

没有awk

awk

答案 2 :(得分:1)

cut -d: -f4 /etc/group | tr , '\n' | grep '.' | \
sort | uniq -c | join -a 1 -o '1.2,1.1' - /dev/null 

或者:

cut -d: -f4 /etc/group | tr , '\n' | grep '.' | \
sort | uniq -c | awk '{ print $2 " " $1  }'

工作原理:

  1. cut out field #4
  2. tr将逗号更改为换行符。
  3. grep删除空行。
  4. sort,计算uniq ue行,使用OP的规格进行打印。

答案 3 :(得分:0)

略微修改的示例输入,包括,分隔名称

$ cat abc.txt 
nobody:*:-2:
nogroup:*:-1:
wheel:*:0:root
daemon:*:1:root
kmem:*:2:root,test
sys:*:3:root
tty:*:4:root,t1,test
operator:*:5:root
mail:*:6:_teamsserver

$ perl -F: -le 'foreach (split /,/,$F[3]){$h{$_}++ if /./} END{foreach (keys %h){print "$_ $h{$_}"}}' abc.txt 
t1 1
_teamsserver 1
root 6
test 2
  • -F::上拆分输入行并保存到@F数组
  • foreach (split /,/,$F[3]),
  • 上重复第四场分割
  • $h{$_}++ if /./如果非空
  • 则递增哈希值
  • END{foreach (keys %h){print "$_ $h{$_}"}}以所需格式打印哈希信息