【问题标题】:update specific field in text file in specific line更新特定行中文本文件中的特定字段
【发布时间】:2013-07-27 11:28:08
【问题描述】:

下面是我可以更新图书数量的代码。但我似乎无法更新我的其他信息,如书名、作者、价格等。 代码如下:

if grep -q "^$bookname:$author:" BookDB.txt
   then 
   read -p "Update Qty to what?" newQty 
   sed -i "s/^\($bookname:$author:[^:]*\):[^:]*:/\1:$newQty:/" BookDB.txt 
   echo "Book's Qty has been updated successfully!" 
   else 
   echo "$0: BookDB.Txt: no '$title' by '$author'" >&2 
   fi

我的数据库是这样的:

Harry Potter - The Half Blood Prince:J.K Rowling:40.30:10:50
The little Red Riding Hood:Dan Lin:40.80:20:10
Harry Potter - The Phoniex:J.K Rowling:50.00:30:20
Harry Potter - The Deathly Hollow:Dan Lin:55.00:33:790
Little Prince:The Prince:15.00:188:9
Lord of The Ring:Johnny Dept:56.80:100:38
Three Little Pig:Andrew Lim:89.10:290:189
All About Ubuntu:Ubuntu Team:76.00:55:133
Catch Me If You Can:Mary Ann:23.60:6:2
Happy Day:Mary Ann:12.99:197:101
haha:gaga:1:10:1

那么我如何更改某些字段,例如当我选择书名 Lord of the ring 作者 johnny Dept 时,我可以将书名更改为可能是国王之王?

Lord of The King:Johnny Dept:56.80:100:38

【问题讨论】:

  • 您应该考虑使用适当的语言来处理此类问题。我不认为 shell 是正确的工具!例如,使用pythonperl 操作csv 文件非常简单易读...
  • 无序的 csv 文件几乎不能称为“数据库”。至少,您需要将条目按可用的顺序排列,然后才能使用“数据库”一词。

标签: linux shell unix sed


【解决方案1】:

user1146332 一样,我也建议切换到更强大的语言。这里是使用 的示例。它使用模块Getopt::Long 来读取参数并在文件中循环查找匹配的行。

这似乎可行,但您需要更好地检查错误,例如,bookauthor 变量在正则表达式中使用之前都已定义。

还有一件事,我使用带有冒号的split() 来提取字段,我不知道您如何处理名称中带有冒号的书,但在这种情况下,您将需要一个额外的模块来解析 CSV,例如Text::CSV 或用更好的split 表达更加努力。

#!/usr/bin/env perl

use strict;
use warnings;
use Getopt::Long;

my ($book, $author, $newbook, $quantity);

my $r = GetOptions(
        q|book=s| => \$book,
        q|author=s| => \$author,
        q|newbook=s| => \$newbook,
        q|quantity=i| => \$quantity,
) or die;

open my $fh, '<', $ARGV[0] or die;

while ( <$fh> ) { 
        chomp;
        my @f = split /:/;
        next if @f < 5;
        if ( $f[0] =~ m/(?i)\Q$book\E/ &&
             $f[1] =~ m/(?i)\Q$author\E/ ) { 
                $f[0] = defined $newbook ? $newbook : $f[0];
                $f[3] = defined $quantity ? $quantity : $f[3];
                printf qq|%s\n|, join q|:|, @f; 
                next;
        }   

        printf qq|%s\n|, $_; 
}

一个例子:

perl script.pl --book="lord of the ring" --author=dep --newbook="Lord of the King" --quantity=99 infile

产量:

Harry Potter - The Half Blood Prince:J.K Rowling:40.30:10:50
The little Red Riding Hood:Dan Lin:40.80:20:10
Harry Potter - The Phoniex:J.K Rowling:50.00:30:20
Harry Potter - The Deathly Hollow:Dan Lin:55.00:33:790
Little Prince:The Prince:15.00:188:9
Lord of the King:Johnny Dept:56.80:99:38
Three Little Pig:Andrew Lim:89.10:290:189
All About Ubuntu:Ubuntu Team:76.00:55:133
Catch Me If You Can:Mary Ann:23.60:6:2
Happy Day:Mary Ann:12.99:197:101
haha:gaga:1:10:1

【讨论】:

    【解决方案2】:

    呢?

    sed 's/\bLord of The Ring\b/Lord of The King/' file
    

    $猫文件 哈利波特 - 混血王子:J.K罗琳:40.30:10:50 小红帽:丹琳:40.80:20:10 哈利波特 - 凤凰:J.K罗琳:50.00:30:20 哈利波特 - 死亡谷:林丹:55.00:33:790 小王子:王子:15.00:188:9 指环王:约翰尼 部门:56.80:100:38 三只小猪:Andrew Lim:89.10:290:189 关于 Ubuntu:Ubuntu 团队:76.00:55:133 如果可以的话,抓住我:玛丽安:23.60:6:2 快乐的一天:玛丽安:12.99:197:101 哈哈:嘎嘎:1:10:1 $ sed 's/\b 魔戒\b/王者之王/' 文件 哈利波特 - 混血王子:J.K罗琳:40.30:10:50 小红帽:丹琳:40.80:20:10 哈利波特 - 凤凰:J.K罗琳:50.00:30:20 哈利波特 - 死亡谷:林丹:55.00:33:790 小王子:王子:15.00:188:9 国王之王:约翰尼部门:56.80:100:38 三只小猪:Andrew Lim:89.10:290:189 关于 Ubuntu:Ubuntu 团队:76.00:55:133 如果可以的话,抓住我:玛丽安:23.60:6:2 快乐的一天:玛丽安:12.99:197:101 哈哈:嘎嘎:1:10:1

    将带有重定向&gt; 的输出发送到新文件或使用sed 的-i 选项进行就地编辑

    • 重定向

      sed 's/\bLord of The Ring\b/Lord of The King/' file>newfile
      
    • 使用 .bak 文件

      sed -i.bak 's/\bLord of The Ring\b/Lord of The King/' file
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      • 2013-01-06
      • 2018-03-24
      相关资源
      最近更新 更多