update specific field in text file in specific lin

2019-02-21 05:22发布

Below is a code that I'm able to update the quantity of my book. But I cant seem to make it so that I can update my other things like book name, author, price etc. Heres the code:

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

My database would be like this:

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

So how could i change certain fields like when i select the book name Lord of the ring author johnny Dept i can change the book name to maybe lord of the kings?

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

2条回答
兄弟一词,经得起流年.
2楼-- · 2019-02-21 05:51

Like user1146332, I also suggest to switch to a more powerful language. Here an example using . It uses module Getopt::Long to read arguments and loops through the file for a matching line.

It seems to work but it's up to you to do a better checking of errors, for example, that both book and author variables are defined before using them in the regular expression.

One more thing, I use split() with a colon to extract fields, I don't know how you handle a book with a colon in its name but in that case you will need an additional module to parse CSV, like Text::CSV or fight harder with a better split expression.

#!/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|, $_; 
}

An example with:

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

Yields:

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
查看更多
Fickle 薄情
3楼-- · 2019-02-21 05:56

What about ?

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

$ cat file
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

$ sed 's/\bLord of The Ring\b/Lord of The King/' file
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: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

Send the output with redirection > to a new file or use sed's -i option for in place editing.

  • redirection

    sed 's/\bLord of The Ring\b/Lord of The King/' file>newfile
    
  • in place etit with .bak file

    sed -i.bak 's/\bLord of The Ring\b/Lord of The King/' file
    
查看更多
登录 后发表回答