处理关联数组的数据

时间:2016-01-29 14:51:16

标签: arrays bash awk sed associative

我有一个如下所示的配置文件:

#!/bin/bash

# lots of other stuff

declare -A PARTITIONS

PARTITIONS[ROOT,DEV]=/dev/mmcblk0p2
PARTITIONS[ROOT,MNT]=/
PARTITIONS[ROOT,FSTYPE]=ext4
PARTITIONS[ROOT,OPTS]='rw,suid,exec,auto,nouser,async,errors=remount-ro,noatime,nodiratime,commit=120 0 1'
PARTITIONS[ROOT,START]=64MB
PARTITIONS[ROOT,END]=6143.9MB
PARTITIONS[ROOT,OWNER]=root.root
PARTITIONS[ROOT,PERMS]=755

PARTITIONS[DATA,DEV]=/dev/mmcblk0p7
PARTITIONS[DATA,MNT]=/data
PARTITIONS[DATA,FSTYPE]=xfs
PARTITIONS[DATA,OPTS]='rw,noexec,auto,user,suid,noatime,nodiratime,async,logbufs=4,noquota 0 3'
PARTITIONS[DATA,START]=12288MB
PARTITIONS[DATA,END]=-1s
PARTITIONS[DATA,OWNER]=root.root
PARTITIONS[DATA,PERMS]=755
等等等。

当我将它包含在配置脚本中并迭代AA的键时,我没有按特定顺序获取它们。键的右侧部分(DEV,MNT ......)是固定的,但并非所有部分都是强制性的,而左侧部分可以是随机的(只是助记符)。

我需要的是左侧部分的列表,以了解必须创建哪些分区,然后找出哪些正确的部分已定义(如果没有,则设置默认值),因此每个分区都将定义明确在实际创建分区之前,将其添加到fstab,mount ...

我们在这里讨论新系统。完成任务的唯一两个选项是Bash和/或Perl。没有JavaScript,没有Python,没有C#脚本,抱歉。 Sed和Awk可用。因为之前的设置步骤是在Bash中完成的,所以我更喜欢普通的Bash(加上Sed / Awk,如果需要的话)解决方案。

当然可以更改配置文件。唯一强制性的是保持键左侧部分的灵活性。

2 个答案:

答案 0 :(得分:1)

awk救援!

$ awk -F'[\\]\\[,]' '/^PARTITIONS/{a[$2]=a[$2]?a[$2] OFS $3:$3}
                               END{for(k in a) print k ": " a[k]}' conf

DATA: DEV MNT FSTYPE OPTS START END OWNER PERMS
ROOT: DEV MNT FSTYPE OPTS START END OWNER PERMS

您可以通过设置OFS来更改正确组件之间的分隔符。

答案 1 :(得分:1)

虽然我倾向于同意@ EdMorton的评论,即awk是一个优秀的工具,但这个问题并不是特别复杂,而bash可能就好了:

# Find all the left-hand keys
declare -A keys
for key in "${!PARTITIONS[@]}"; do
  keys[${key%%,*}]=1
done

# Set defaults and/or check validity
errors=0
for key in "${!keys[@]}"; do
  # Set a default
  : "${PARTITIONS[$key,FSTYPE]:=ext4}"

  # Make sure a setting exists.
  # -v requires v4.2; otherwise use -n/-z. Maybe you
  # want those anyway, since a blank config might be an error.
  if [[ ! -v PARTITIONS[$key,MNT] ]]; then
    printf "MNT key missing for partition %s\n" "$key" >>/dev/stderr
    # Remove it from the set so it doesn't show up later
    unset keys[$key]
    ((errors++))
  fi

  # Etc.
done

# For debugging purposes, just print out the settings
for key in "${!keys[@]}"; do
  printf "$key:"
  for field in DEV MNT FSTYPE OPTS START END OWNER PERMS; do
    printf " %s=%b" $field "${PARTITIONS[$key,$field]}"
  done
  echo
done 

if ((errors)); then
  printf "Config errors. Not proceeding\n" >> /dev/stderr
  return 1
fi

# Do what needs to be done
# probably another loop over keys
相关问题