string 使用 Sed 替换包含字符串的整行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11245144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 01:31:29  来源:igfitidea点击:

Replace whole line containing a string using Sed

stringshellsed

提问by Rahul

I have a text file which has a particular line something like

我有一个文本文件,它有一个特定的行,比如

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

I need to replace the whole line above with

我需要用上面的整行替换

This line is removed by the admin.

The search keyword is TEXT_TO_BE_REPLACED

搜索关键字是 TEXT_TO_BE_REPLACED

I need to write a shell script for this. How can I achieve this using sed?

我需要为此编写一个shell脚本。我怎样才能做到这一点sed

回答by Todd A. Jacobs

You can use the changecommand to replace the entire line, and the -iflag to make the changes in-place. For example, using GNU sed:

您可以使用更改命令替换整行,并使用-i标志进行就地更改。例如,使用 GNU sed:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

回答by Thor

You need to use wildards (.*) before and after to replace the whole line:

您需要在.*前后使用通配符 ( ) 来替换整行:

sed 's/.*TEXT_TO_BE_REPLACED.*/This line is removed by the admin./'

回答by skensell

The accepted answer did not work for me for several reasons:

由于以下几个原因,接受的答案对我不起作用:

  • my version of sed does not like -iwith a zero length extension
  • the syntax of the c\command is weird and I couldn't get it to work
  • I didn't realize some of my issues are coming from unescaped slashes
  • 我的 sed 版本不喜欢-i零长度扩展
  • c\命令的语法很奇怪,我无法让它工作
  • 我没有意识到我的一些问题来自未转义的斜杠

So here is the solution I came up with which I think should work for most cases:

所以这是我想出的解决方案,我认为它适用于大多数情况:

function escape_slashes {
    sed 's/\//\\//g' 
}

function change_line {
    local OLD_LINE_PATTERN=; shift
    local NEW_LINE=; shift
    local FILE=

    local NEW=$(echo "${NEW_LINE}" | escape_slashes)
    sed -i .bak '/'"${OLD_LINE_PATTERN}"'/s/.*/'"${NEW}"'/' "${FILE}"
    mv "${FILE}.bak" /tmp/
}

So the sample usage to fix the problem posed:

因此,解决问题的示例用法提出了:

change_line "TEXT_TO_BE_REPLACED" "This line is removed by the admin." yourFile

回答by user4256255

The Answer above:

上面的答案:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

Works fine if the replacement string/line is not a variable.

如果替换字符串/行不是变量,则工作正常。

The issue is that on Redhat 5 the \after the cescapes the $. A double \\did not work either (at least on Redhat 5).

问题是在 Redhat 5 上\c转义$. double\\也不起作用(至少在 Redhat 5 上)。

Through hit and trial, I discovered that the \after the cis redundant if your replacement string/line is only a single line. So I did not use \after the c, used a variable as a single replacement line and it was joy.

通过点击和试用,我发现如果您的替换字符串/行只是一行,则\之后c是多余的。所以我没有\c, 之后使用变量作为单个替换行,这很高兴。

The code would look something like:

代码如下所示:

sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo

Note the use of double quotes instead of single quotes.

请注意使用双引号而不是单引号。

回答by b_laoshi

All of the answers provided so far assume that you know something about the text to be replaced which makes sense, since that's what the OP asked. I'm providing an answer that assumes you know nothing about the text to be replaced and that there may be a separate line in the file with the same or similar content that you do not want to be replaced. Furthermore, I'm assuming you know the line number of the line to be replaced.

到目前为止提供的所有答案都假设您对要替换的文本有所了解,这是有道理的,因为这就是 OP 所要求的。我提供的答案假定您对要替换的文本一无所知,并且文件中可能有单独的一行具有您不想替换的相同或相似的内容。此外,我假设您知道要替换的行的行号。

The following examples demonstrate the removing or changing of text by specific line numbers:

以下示例演示了按特定行号删除或更改文本:

# replace line 17 with some replacement text and make changes in file (-i switch)
# the "-i" switch indicates that we want to change the file. Leave it out if you'd
#   just like to see the potential changes output to the terminal window.
# "17s" indicates that we're searching line 17
# ".*" indicates that we want to change the text of the entire line
# "REPLACEMENT-TEXT" is the new text to put on that line
# "PATH-TO-FILE" tells us what file to operate on
sed -i '17s/.*/REPLACEMENT-TEXT/' PATH-TO-FILE

# replace specific text on line 3
sed -i '3s/TEXT-TO-REPLACE/REPLACEMENT-TEXT/'

回答by Grain

for manipulation of config files

用于操作配置文件

i came up with this solution inspired by skensell answer

我想出了这个解决方案的灵感来自skensell 的答案

configLine [searchPattern] [replaceLine] [filePath]

configLine [searchPattern] [replaceLine] [filePath]

it will:

它会:

  • create the file if not exists
  • replace the whole line (all lines) where searchPatternmatched
  • add replaceLineon the end of the file if pattern was not found
  • 如果不存在则创建文件
  • 替换searchPattern匹配的整行(所有行)
  • 如果找不到模式,则在文件末尾添加replaceLine

Function:

功能:

function configLine {
  local OLD_LINE_PATTERN=; shift
  local NEW_LINE=; shift
  local FILE=
  local NEW=$(echo "${NEW_LINE}" | sed 's/\//\\//g')
  touch "${FILE}"
  sed -i '/'"${OLD_LINE_PATTERN}"'/{s/.*/'"${NEW}"'/;h};${x;/./{x;q100};x}' "${FILE}"
  if [[ $? -ne 100 ]] && [[ ${NEW_LINE} != '' ]]
  then
    echo "${NEW_LINE}" >> "${FILE}"
  fi
}

the crazy exit status magic comes from https://stackoverflow.com/a/12145797/1262663

疯狂的退出状态魔法来自https://stackoverflow.com/a/12145797/1262663

回答by nkl

bash-4.1$ new_db_host="DB_HOSTNAME=good replaced with 122.334.567.90"
bash-4.1$ 
bash-4.1$ sed -i "/DB_HOST/c $new_db_host" test4sed
vim test4sed
'
'
'
DB_HOSTNAME=good replaced with 122.334.567.90
'

it works fine

它工作正常

回答by sjordi

cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file    
done 

find_replace file contains 2 columns, c1 with pattern to match, c2 with replacement, the sed loop replaces each line conatining one of the pattern of variable 1

find_replace 文件包含 2 列,c1 带有要匹配的模式,c2 带有替换,sed 循环替换包含变量 1 模式之一的每一行

回答by Martin Pfeffer

In my makefile I use this:

在我的 makefile 中,我使用了这个:

@sed -i '/.*Revision:.*/c\'"`svn info -R main.cpp | awk '/^Rev/'`"'' README.md

PS: DO NOTforget that the -i changes actually the text in the file... so if the pattern you defined as "Revision" will change, you will also change the pattern to replace.

PS:不要忘记 -i 实际上更改了文件中的文本...因此,如果您定义为“修订版”的模式将更改,您也将更改要替换的模式。

Example output:

示例输出:

Abc-Project written by John Doe

Revision: 1190

John Doe 编写的 Abc 项目

修订版:1190

So if you set the pattern "Revision: 1190" it's obviously not the same as you defined them as "Revision:" only...

因此,如果您设置模式“修订版:1190”,它显然与您将它们定义为“修订版:”不同......

回答by Ritesh Borkar

Below command is working for me. Which is working with variables

下面的命令对我有用。哪个正在处理变量

sed -i "/\<$E\>/c $D" "$B"