sed擦除所有内容而不是改变单个字段

时间:2015-01-10 07:36:05

标签: shell sed

嗨,我有这个代码,旨在更新单个字段标题,但它以删除所有内容结束。需要一些帮助

BookDB.txt:

The Hunger Games:Suzanne Collins:1:1:1
Weapon X:Stan Lee:1:1:1
Weapon X:stan lim:1:1:1
function update_title
{
   echo "Title: "
   read title
   echo "Author: "
   read author
   grep -iqs "$title:$author:" BookDB.txt && echo "Book Found!"
   echo "New Title: "
   read title_new   
   sed -i "/^$author:/ s/$title/$title_new/" BookDB.txt || tee BookDB.txt && echo "Book Title has been updated sucessfully!"
}

2 个答案:

答案 0 :(得分:2)

回答修订问题

需要更改sed命令,因为标题首先出现在行上,而不是作者。同样删除tee命令的原因与下面解释的相同。因此,定义函数如下:

update_title () 
{ 
    echo "Title: ";
    read title;
    echo "Author: ";
    read author;
    grep -iqs "$title:$author:" BookDB.txt && echo "Book Found!";
    echo "New Title: ";
    read title_new;
    sed -i "/:$author:/ s/^$title/$title_new/" BookDB.txt && echo "Book Title has been updated sucessfully!"
}

例如,调用函数:

$ update_title 
Title: 
Weapon X
Author: 
Stan Lee
Book Found!
New Title: 
Weapon XYZ
Book Title has been updated sucessfully!

结果是:

$ cat BookDB.txt 
The Hunger Games:Suzanne Collins:1:1:1
Weapon XYZ:Stan Lee:1:1:1
Weapon X:stan lim:1:1:1

回答原始问题

替换:

sed -i "/^$author:/ s/$title/$title_new/" BookDB.txt || tee BookDB.txt && echo "Book Title has been updated sucessfully!"

有了这个:

sed -i "/^$author:/ s/$title/$title_new/" BookDB.txt && echo "Book Title has been updated sucessfully!"

第一行要求sed重写BookDB.txt。然后它要求tee覆盖同一个文件。解决方案是只做第一个。

解释

命令如:

sed 's/old/new/' file >file

或:

sed 's/old/new/' file | tee file

将不可靠。它们在同时写入文件时尝试从文件中读取。根据文件的缓冲方式,这种类型的命令可能偶尔会起作用,但永远不会被信任。

sed -i专门用于避免此问题。它写入临时文件,并在成功保存所有更改后,覆盖源文件。

实施例

让我们定义这个功能:

function update_title
{
   echo "Title: "
   read title
   echo "Author: "
   read author
   grep -iqs "$title:$author:" BookDB.txt && echo "Book Found!"
   echo "New Title: "
   read title_new   
   sed -i "/^$author:/ s/$title/$title_new/" BookDB.txt && echo "Book Title has been updated sucessfully!"
}

现在,让我们使用它:

$ cat BookDB.txt 
Tim:Old Title:
Tom:Older Title:
$ update_title 
Title: 
Old Title
Author: 
Tim
New Title: 
New Title
Book Title has been updated sucessfully!
$ cat BookDB.txt 
Tim:New Title:
Tom:Older Title:

旧标题已成功更换。

警告

此函数将shell变量直接替换为sed命令。如果用户不知道sed-active字符的强大功能,结果可能会令人惊讶。

举个例子:

$ update_title 
Title: 
.*
Author: 
Tim
New Title: 
This & That
Book Title has been updated sucessfully!

现在,观察新文件:

$ cat BookDB.txt 
This Tim:New Title: That
Tom:Older Title:

OSX

在OSX上,-i的{​​{1}}选项需要参数。对于OSX以及可能的其他BSD平台,请将函数定义中的sed行替换为:

sed

或者,

   sed -i .bak "/^$author:/ s/$title/$title_new/" BookDB.txt && echo "Book Title has been updated sucessfully!"

答案 1 :(得分:1)

使用这个,因为第一个字段绝对是标题所以你必须把标题放在前面

sed -i "/^$title:$author:/ s/$title/$title_new/" BookDB.txt