我正在尝试使用bash中的while循环遍历3个文件的内容。它们包含名称,aws帐户和aws帐号的列表。
但是循环是不正确的,它会不断重复列表中的名字和列表中的第一个aws环境。
这是我看到的输出:
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-lab
这些是我要读取的文件:
aws_users_all="source_files/aws_users_all.txt"
示例输出:
aadatiya
abigailcharles
tdunphy
broberts
下一个文件:
aws_env_list="source_files/aws_environments_all.txt"
示例输出:
company-lab
company-stage
company-nonprod
company-prod
最后一个文件: aws_account_numbers =“ source_files / aws_account_numbers.txt” 样本输出:
123456789191
987654321211
456721231213
123213512321
这是循环错误的代码:
ofile=source_files/aws_access_keys/company-aws-access-keys-all-accounts.csv
while IFS= read -r aws_user_name
do
while IFS= read -r aws_key
do
while IFS= read -r aws_account_num
do
user_lives_here=$(aws iam get-user --user-name "$aws_user_name" --profile="$aws_key" 2> /dev/null | jq -r '.User.UserName')
if [[ -z "$user_lives_here" ]]; then
printf "AWS user name: %s does not exist in AWS account: %s\\n(%s)" "$aws_user_name" "$aws_key" "$aws_account_num"
else
echo "$aws_user_name,$user_access_key1,$key1_date_created,$key1_last_used,$key1AgeDays,$aws_key,$aws_account_num" >> $ofile
fi
done < "$aws_account_numbers"
done < "$aws_env_list"
done < "$aws_users_all"
如果我取出一个级别(帐号级别),脚本将按预期运行并产生以下输出:
AWS user name: aadatiya does not exist in AWS account: company-lab
AWS user name: aadatiya does not exist in AWS account: company-bill
AWS user name: aadatiya does not exist in AWS account: company-stage
AWS user name: aadatiya does not exist in AWS account: company-dlab
AWS user name: aadatiya does not exist in AWS account: company-nonprod
AWS user name: aadatiya does not exist in AWS account: company-prod
AWS user name: aadatiya does not exist in AWS account: company-govcloud-admin-nonprod
AWS user name: abigailcharles does not exist in AWS account: company-lab
AWS user name: abigailcharles does not exist in AWS account: company-bill
AWS user name: abigailcharles does not exist in AWS account: company-stage
AWS user name: abigailcharles does not exist in AWS account: company-dlab
AWS user name: abigailcharles does not exist in AWS account: company-nonprod
AWS user name: abigailcharles does not exist in AWS account: company-prod
AWS user name: abigailcharles does not exist in AWS account: company-govcloud-admin-nonprod
我刚刚注释了此级别,它可以工作:
#while IFS= read -r aws_account_num
#do
#done
如何正确执行此操作,以便循环浏览每个名称,aws帐户和AWS帐号,以便每个条目显示一次?
答案 0 :(得分:4)
您想要使用三个不同的文件描述符的一个循环调用read
三次。
while IFS= read -r aws_user_name
IFS= read -r aws_key <&3
IFS= read -r aws_account_num <&4; do
...
done < "$aws_users_all" 3< "$aws_env_list" 4< "$aws_account_numbers"
答案 1 :(得分:3)
paste
命令的方式:while read aws_user_name aws_key aws_account_num ;do
printf "User: %-16s Key: %-22s AccNum: %s\n" \
$aws_user_name $aws_key $aws_account_num
# ...
done < <(
paste "$aws_users_all" "$aws_env_list" "$aws_account_numbers"
)
示例:
User: aadatiya Key: company-lab AccNum: 123456789191
User: abigailcharles Key: company-stage AccNum: 987654321211
User: tdunphy Key: company-nonprod AccNum: 456721231213
User: broberts Key: company-prod AccNum: 123213512321
Nota:这很简单,而每个文件中确实包含一行1字。
...如果您打算在源文件中使用空间,则可以使用另一个定界符:
while IFS=@ read -r aws_user_name aws_key aws_account_num ;do
printf "User: %-16s Key: %-22s AccNum: %s\n" \
"$aws_user_name" "$aws_key" "$aws_account_num"
# ....
done < <(
paste -d@ "$aws_users_all" "$aws_env_list" "$aws_account_numbers"
)
在@chepner解决方案附近:
exec 3<$aws_env_list
exec 4<$aws_account_numbers
while read aws_user_name ;do
read -u 3 aws_key
read -u 4 aws_account_num
printf "User: %-16s Key: %-22s AccNum: %s\n" \
"$aws_user_name" "$aws_key" "$aws_account_num"
# ...
done <$aws_users_all
exec 3<&-
exec 4<&-
注意:最后两行将关闭 FD 3和4。
答案 2 :(得分:0)
一种方法是在处理之前将所有输入数据加载到数组中
IFS= mapfile -t aws_users <"$aws_users_all"
IFS= mapfile -t aws_envs <"$aws_env_list"
IFS= mapfile -t aws_acct_nums <"$aws_account_numbers"
for aws_user_name in "${aws_users[@]}" ; do
for idx in ${!aws_envs[*]} ; do
aws_key=${aws_envs[idx]}
aws_account_num=${aws_acct_nums[idx]}
# Code using $aws_user_name, $aws_key, and $aws_account_num
...
done
done
请注意,mapfile
是Bash 4.0引入的,因此,如果您使用的是较旧版本的Bash,则此功能将无效。请参阅Read lines from a file into a Bash array,了解适用于较早版本的替代方法(但请注意,可接受的答案非常糟糕)。
将文件加载到内存中似乎是一个坏主意,但实际上这不太可能成为问题。现代机器具有大量内存,而Bash在几乎所有方面都非常慢。如果要加载到内存中的数据太多,则可能有方式要用Bash代码逐行处理的数据太多。