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

sed erasing everything instead of changing single field

您好,我有这段代码旨在更新单个字段标题,但它以擦除所有内容而告终。需要一些帮助

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!"
}

修改问题的答案

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 上,sed-i 选项需要一个参数。对于 OSX,可能还有其他 BSD 平台,将函数定义中的 sed 行替换为:

   sed -i .bak "/^$author:/ s/$title/$title_new/" 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 -i "/^$title:$author:/ s/$title/$title_new/" BookDB.txt