bash脚本mapfile处理多数组异常:查询用户信息始终返回第一条数据
问题:查询patron.txt用户信息时无法匹配对应ID
使用mapfile将文本存入数组编写bash脚本,查询patron.txt中的用户信息时,无论输入哪个用户ID,都只返回第一条用户的姓名、联系方式和邮箱,无法正确匹配对应ID的数据。
相关文件内容
patron.txt内容:
123456:Gerald:012-9999999:asdf@gmail.com 999999:Tom:010-8888888:zxcv@gmail.com
当前代码
#!/bin/bash echo "Search Patron Details" echo -n "Enter Patron ID: " read id1 mapfile -d: -t array < <(grep -i "$id1" patron.txt) echo "Fullname (auto display): ${array[1]}" echo "Contact Number (auto display): ${array[2]}" echo "Email Adddress (auto display): ${array[3]}" echo -n "Would you like to continue searching for patrons? (y)es or (q)uit: " read option case $option in y|Y) bash show_details;; q|Q) bash main_menu;; *) echo "Invalid entry";;; esac
预期结果
Search Patron Details Enter Patron ID: 999999 Fullname (auto display): Tom Contact Number (auto display): 010-8888888 Email Adddress (auto display): zxcv@gmail.com Would you like to continue searching for patrons? (y)es or (q)uit: y Search Patron Details Enter Patron ID: 123456 Fullname (auto display): Gerald Contact Number (auto display): 012-9999999 Email Adddress (auto display): asdf@gmail.com
实际结果
Search Patron Details Enter Patron ID: 999999 Fullname (auto display): Gerald Contact Number (auto display): 012-9999999 Email Adddress (auto display): asdf@gmail.com 999999 Would you like to continue searching for patrons? (y)es or (q)uit: y Search Patron Details Enter Patron ID: 123456 Fullname (auto display): Gerald Contact Number (auto display): 012-9999999 Email Adddress (auto display): asdf@gmail.com
问题原因与解决方法
问题根源
- grep匹配规则不精确:原代码中
grep -i "$id1"会匹配所有包含该ID数字的行,比如输入999999时,会匹配第一行(联系方式字段包含999999)和第二行(ID字段是999999),导致mapfile读取了两行内容,分割后取前几个元素自然是第一行的信息。 - mapfile分割逻辑不适合单行数据:
mapfile -d:会把所有:作为分隔符,包括多行内容的拼接,导致数组元素混乱。
修复后的代码
改用IFS=: read直接分割匹配到的单行数据,同时精确匹配行首的ID:
#!/bin/bash echo "Search Patron Details" echo -n "Enter Patron ID: " read id1 # 精确匹配行首的ID(ID后必须跟冒号),避免误匹配其他字段 patron_data=$(grep "^$id1:" patron.txt) # 判断是否找到对应ID if [ -z "$patron_data" ]; then echo "Patron ID $id1 not found!" echo -n "Would you like to continue searching for patrons? (y)es or (q)uit: " read option case $option in y|Y) bash show_details;; q|Q) bash main_menu;; *) echo "Invalid entry";; esac exit 0 fi # 用冒号分割数据到变量 IFS=: read -r _ fullname contact email <<< "$patron_data" echo "Fullname (auto display): $fullname" echo "Contact Number (auto display): $contact" echo "Email Adddress (auto display): $email" echo -n "Would you like to continue searching for patrons? (y)es or (q)uit: " read option case $option in y|Y) bash show_details;; q|Q) bash main_menu;; *) echo "Invalid entry";; esac
关键修改点
- 用
grep "^$id1:"精确匹配行首以ID:开头的行,确保只返回对应ID的用户数据。 - 用
IFS=: read直接将匹配到的单行数据分割到变量中,比mapfile更适合单行数据的处理。 - 增加了ID不存在的判断逻辑,提升脚本健壮性。
内容的提问来源于stack exchange,提问作者Gerald Loo
相关产品推荐
相关产品推荐

