捕获文件并分离列并使用数组添加

时间:2014-03-03 06:01:08

标签: arrays linux bash awk

我想管理 / etc / passwd 并为每列添加名称..

我想从数组中读取...

我尝试的是以下bash:

#!/bin/bash

FILE="/etc/passwd"
arr=( $(awk < $FILE -F: '{print $1 $5 $6 $7}') )

for Username Realname Homedir Loginshell in "${arr[@]}"; do
    result=$(printf 'Username: %s Realname: %s Homedir: %s Loginshell: %s' "$Username" "$Realname" "$Homedir" "Loginshell")
    echo "$result"
done

但是有错误:

./u.sh: line 6: syntax error near unexpected token `Realname'
./u.sh: line 6: `for Username Realname Homedir Loginshell in "${arr[@]}"; do'

第二个问题是:

如何在此类脚本中读取$FILE作为参数...因为更改脚本时如下:

#!/bin/bash

if [ "$#" -ne "1" ]; then
    echo "Usage: `basename $0` <input-file>"
    exit 1
fi

arr=( $(awk < $1 -F: '{print $1 $2 $6 $7}') )

for Username Realname Homedir Loginshell in "${arr[@]}"; do
    result=$(printf 'Username: %s Realname: %s Homedir: %s Loginshell: %s' "$Username" "$Realname" "$Homedir" "Loginshell")
    echo "$result"
done

它会崩溃......

由于

2 个答案:

答案 0 :(得分:2)

像这样使用:

while read Username Realname Homedir Loginshell; do
    result=$(printf "Username: %s Realname: %s Homedir: %s Loginshell: %s" "$Username" "$Realname" "$Homedir" "Loginshell")
    echo "$result"
done < <(awk -F: '{print $1 $2 $6 $7}' /etc/passwd)

编辑:您可以使用awk:

if (($# == 0)); then
   echo "Usage: `basename $0` <input-file>"
   exit 1
fi
FILENAME="$1"

awk -F: '{printf "Username: %s Realname: %s Homedir: %s Loginshell: %s\n",
       $1, $2, $6, $7}' "$FILENAME"

答案 1 :(得分:1)

此方法避免使用awk,但使用bash的IFS分隔FILE中的字段:

FILE="/etc/passwd"
while IFS=: read Username pass uid gid Realname Homedir Loginshell; do
    result=$(printf 'Username: %s Realname: %s Homedir: %s Loginshell: %s' "$Username" "$Realname" "$Homedir" "$Loginshell")
    echo "$result"
done <"$FILE"

提供文件名作为参数(根据问题2):

if [ "$#" -ne "1" ]; then
    echo "Usage: `basename $0` <input-file>"
    exit 1
fi
FILE=$1

while IFS=: read Username pass uid gid Realname Homedir Loginshell; do
    result=$(printf 'Username: %s Realname: %s Homedir: %s Loginshell: %s' "$Username" "$Realname" "$Homedir" "$Loginshell")
    echo "$result"
done <"$FILE"

如果你想使用数组,那么:

#!/bin/bash
if [ "$#" -ne "1" ]; then
    echo "Usage: `basename $0` <input-file>"
    exit 1
fi
FILE=$1

#declare -a fields
IFS=:
while read line; do
    fields=($line)
    result=$(printf 'Username: %s Realname: %s Homedir: %s Loginshell: %s' "${fields[0]}" "${fields[4]}" "${fields[5]}" "${fields[6]}")
    echo "$result"
done <"$FILE"

上面一次只读一行/etc/passwd。将IFS设置为冒号后,每行将使用fields=($line)转换为数组。为避免出现意外,您可能需要在执行依赖于IFS正常字词分隔规则的任何bash代码之前将bash重置为其默认值。

附加:

这是尝试漂亮打印输出:

#!/bin/bash
if [ "$#" -ne "1" ]; then
    echo "Usage: `basename $0` <input-file>"
    exit 1
fi
FILE=$1

{
echo "========:========:=======:=========="
echo "Username:Realname:Homedir:Loginshell"
echo "========:========:=======:=========="

IFS=:
while read line; do
    fields=($line)
    echo "${fields[0]}:${fields[4]}:${fields[5]}:${fields[6]}"
done < "$FILE"
} | column -nts:

默认情况下,column按空格分隔字段。但是,realname输出字段可以包含空格。因此,使用-s:选项,以便column在输入上使用冒号分隔的字段。为了确保标题与数据字段对齐,标题和数据都会提交到column的同一个实例。