You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
}

问题原因

  1. sed匹配逻辑错误:当前stock是减1后的值,而sed命令试图匹配$titulo + 非空格字符 + 新库存值,这在原文件中根本不存在(原文件中是旧库存值),自然无法匹配替换。
  2. 潜在风险:若标题包含空格或正则元字符(如.、*),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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:07:05