如何将CAT系统调用的输出重定向到变量并解析变量数据

时间:2014-02-03 08:56:12

标签: linux bash

我主要强调的是从/etc/passwd文件中提取用户名,然后存储在数组列表中我可以逐个显示它,我已经创建了简单的脚本,如下所示

#!/bin/bash


cat "/etc/passwd" > OUTPUT

echo -e $OUTPUT
IFS=:
read -ra ADDR <<< "$OUTPUT"

for i in "${ADDR[@]}"; do
    echo -e $i
done

的输出
>    cat /etc/passwd

   root:$1$L15vXdMd$SVx9qKAzHtLcqGN8n2SIc.:0:0:root:/:/bin/sh
   sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/bin/false
   super:x:1111:1100:Ldap user:/opt/www/usr/super:/bin/sh
   admin:x:1107:1100:Ldap user:/opt/www/usr/admin:/opt/www/jv/bin/cliInit.sh
   guest:x:1101:1100:Ldap user:/opt/www/usr/guest:/opt/www/jv/bin/cliInit.sh
   postgres:x:1000:1000:Linux User,,,:/home/postgres:/bin/sh
   albert:x:1114:1100:Ldap user:/opt/wwwl/usr/albert:/opt/www/jv/bin/cliInit.sh
   ritesh112:x:1125:1001:RADIUS user:/opt/www/usr/ritesh112:/opt/dell/mc/bin/cliInit.sh

可能是我在上面的脚本中做了错误的方式(这就是我问这个问题的原因)。根据我的逻辑,首先将/etc/passwd重定向到(cat "/etc/passwd" > OUTPUT的任何变量,不知道它是对的或者错误另外,尝试read -ra ADDR <<< "cat /etc/passwd"但没有工作的替代方案)然后将输出分隔IFS=: bash变量并将所有用户名存储在数组ADDR中。

我希望脚本输出如下,sshdpostgres用户名除外。

root
super
admin
guest
albert
ritesh112

但是没有任何人有想法吗?

6 个答案:

答案 0 :(得分:4)

cat "/etc/passwd" > OUTPUT

不创建变量,只是将/etc/passwd复制到名为OUTPUT的文件中。要将内容添加到变量中,您可以尝试OUTPUT=$(cat /etc/passwd)

但你可以简单地使用cut:

cut -d: -f1 /etc/passwd

答案 1 :(得分:2)

由于似乎没有其他人像你问的那样把结果放在一个数组中,我会提供这个:

declare -a array=($(awk -F: '!/^sshd|^postgres/{print $1}' /etc/passwd))
echo ${array[1]}
root
echo ${array[2]}
daemon

答案 2 :(得分:1)

有了一点awk,你可以用

达到目标
i=0
awk -F:  '{ print $1 }' /etc/passwd | egrep -v '^(sshd|postgres)$' |while read; do
    array[i]=$REPLY
    i=$((i + 1))
done

#output 5th item in array 
echo ${array[4]}
#output array length
echo ${#array[*]}

答案 3 :(得分:1)

@perreal已经解释了你的脚本有什么问题。这就是我要做的事情:

cut -d: -f1 /etc/passwd | egrep -v '^(sshd|postgres)$'

说明:

cut打印输入的字段。 -d:表示字段与:分隔,-f1选择第一个字段。

egrep进一步过滤cut的输出。 -v表示“打印任何不匹配的内容”,正则表达式恰好匹配两个用户名。因此它仍会打印sshd2postgresadmin

将所有内容放入数组:

declare -a array=($(cut -d: -f1 /etc/passwd | egrep -v '^(sshd|postgres)$'))

(注意:BASH语法;其他shell工作略有不同)。

答案 4 :(得分:1)

不要将输出存储在变量/数组中(在某些情况下你可以得到各种缓冲问题 - 虽然没有使用/ etc / passwd,并且根本没有必要),只需做一些像解析它的行按行或使用等工具作为perreal suggested

e.g。

#!/bin/bash

while read -r line; do 
  echo "${line%%:*}"
done < /etc/passwd

${line%%:*}将移除与:*匹配的最长后缀,即包含第一个:

之后的所有内容

要获取数组,您只需将其更改为(还要注意不包括数组中的postgressshd。执行此操作的方法数量,但这应该在这里足够好了)

#!/bin/bash

while read -r line; do
  [[ "${line%%:*}" != postgres && "${line%%:*}" != sshd ]] && arr+=("${line%%:*}")
done < /etc/passwd

for i in "${arr[@]}"; do
  echo -e "$i"
done

或者执行命令替换之类的操作(但同样,在大多数情况下不是最佳实践)

IFS=$'\n'
arr=($(< /etc/passwd))

答案 5 :(得分:1)

您可以尝试以下方式:

declare -a array
i=0
cut -d: -f1 /etc/passwd|egrep -v "^(sshd|postgres)$"|while read; do
    array[$i]="$REPLY"
    i=$((i + 1))
done
echo "${array[@]}"

或类似的东西:

declare -a array
i=0
while read; do
    array[$i]="$REPLY"
    i=$((i + 1))
done <<< "$(cut -d: -f1 /etc/passwd|egrep -v '^(sshd|postgres)$')"
echo "${array[@]}"

或者:

declare -a array
i=0
while read; do
    array[$i]="$REPLY"
    i=$((i + 1))
done < <(cut -d: -f1 /etc/passwd|egrep -v '^(sshd|postgres)$')
echo "${array[@]}"

否则,您也可以使用awk而不是cutegrep(两者):

awk -F":" '($1 != "sshd" && $1 != "postgres"){print $1}' /etc/passwd|while read; do
    #...
done