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