awk提取库存值后sed替换失效的Shell脚本技术问题求助
问题分析与解决
问题描述
尝试通过awk提取库存值并减1后更新文件,但sed替换命令失效。当livros文件中某本书库存为71时,调用vender_livro()函数后库存未变为70。以下环节均正常:
- 能正确定位目标行
stock=$(echo "$linha" | awk '{print $6}')可正确获取库存值stock=$(($stock - 1))减1操作执行正常
核心问题:
下面的sed命令无法完成替换:
sed -i "s/$titulo[^ ]* $stock/$titulo $stock/" livros
数据格式
livros文件每行格式为空格分隔的字段:
Author Title Description Genre NumPages Stock Price
原函数代码
vender_livro() { echo " -----------------" echo " | Sell Book |" echo " -----------------" read -p "Enter the title of the book to sell: " titulo if grep -q "$titulo" livros; then linha=$(grep "$titulo" livros) stock=$(echo "$linha" | awk '{print $6}') stock=$(($stock - 1)) sed -i "s/$titulo[^ ]* $stock/$titulo $stock/" livros echo "Book sold successfully!" else echo "No book found in the database." fi echo read -p "Press Enter to continue" continue clear }
问题原因
- sed匹配逻辑错误:当前
stock是减1后的值,而sed命令试图匹配$titulo+ 非空格字符 + 新库存值,这在原文件中根本不存在(原文件中是旧库存值),自然无法匹配替换。 - 潜在风险:若标题包含空格或正则元字符(如
.、*),grep和sed的匹配会出现异常。
解决方案
方案1:修正sed命令逻辑
先保存旧库存值,再定位目标行替换旧值为新值:
vender_livro() { echo " -----------------" echo " | Sell Book |" echo " -----------------" read -p "Enter the title of the book to sell: " titulo if grep -q "$titulo" livros; then linha=$(grep "$titulo" livros) old_stock=$(echo "$linha" | awk '{print $6}') new_stock=$(($old_stock - 1)) # 定位包含标题的行,替换旧库存为新库存(前后加空格避免误匹配) sed -i "/$titulo/s/ $old_stock / $new_stock /" livros echo "Book sold successfully!" else echo "No book found in the database." fi echo read -p "Press Enter to continue" continue clear }
方案2:用awk一站式处理(更可靠)
awk可以直接定位目标行并修改字段,避免grep+sed的组合问题,同时天然支持字段操作:
vender_livro() { echo " -----------------" echo " | Sell Book |" echo " -----------------" read -p "Enter the title of the book to sell: " titulo # 用awk检查是否存在目标行并更新库存 awk -v titulo="$titulo" ' { # 匹配包含标题的行 if ($0 ~ titulo) { $6 = $6 - 1 # 库存直接减1 } print $0 }' livros > temp_livros && mv temp_livros livros # 检查是否有修改(可选) if grep -q "$titulo" livros; then echo "Book sold successfully!" else echo "No book found in the database." fi echo read -p "Press Enter to continue" continue clear }
额外优化(针对标题含空格/特殊字符)
如果标题可能包含空格或正则元字符,需要对标题进行转义,避免grep/awk匹配出错。例如在awk中用index()函数精确匹配:
awk -v titulo="$titulo" ' { if (index($0, titulo) != 0) { $6 = $6 - 1 } print $0 }' livros > temp_livros && mv temp_livros livros
内容的提问来源于stack exchange,提问作者Antônio Velez
相关产品推荐
相关产品推荐

