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

时间:2012-06-28 12:55:27

标签: string shell sed

我有一个文本文件,其中包含类似

的特定行
sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext

我需要用

替换上面的整行
This line is removed by the admin.

搜索关键字为TEXT_TO_BE_REPLACED

我需要为此编写一个shell脚本。如何使用sed

实现此目的

14 个答案:

答案 0 :(得分:414)

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

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

答案 1 :(得分:129)

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

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

答案 2 :(得分:17)

接受的答案对我不起作用有几个原因:

  • 我的sed版本不喜欢长度为零的-i
  • c\命令的语法很奇怪,我无法让它工作
  • 我没有意识到我的一些问题来自未转义的斜杠

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

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

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

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

因此用于修复问题的示例用法:

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

答案 3 :(得分:10)

上面的答案:

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

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

问题是,在\ c $之后{4}},在Redhat 5上\\。双\也不起作用(至少在Redhat 5上)。

通过点击和试用,我发现如果您的替换字符串/行只是一行,c之后的\是多余的。所以我没有在c之后使用sed -i "/TEXT_TO_BE_REPLACED/c $REPLACEMENT_TEXT_STRING" /tmp/foo ,使用变量作为单个替换行,这很快乐。

代码看起来像:

{{1}}

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

答案 4 :(得分:3)

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

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

# 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/'

答案 5 :(得分:2)

用于配置文件的操作

我想出了受skensell answer启发的此解决方案

configLine [searchPattern] [replaceLine] [filePath]

它将:

  • 创建文件(如果不存在)
  • 替换匹配 searchPattern 的整行(所有行)
  • 如果未找到模式,请在文件末尾
  • 添加 replaceLine

功能:

function configLine {
  local OLD_LINE_PATTERN=$1; shift
  local NEW_LINE=$1; shift
  local FILE=$1
  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
}

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

答案 6 :(得分:1)

In my makefile I use this:

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

PS: DO NOT forget 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.

Example output:

Abc-Project written by John Doe

Revision: 1190

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

答案 7 :(得分:1)

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
'

一切正常

答案 8 :(得分:1)

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

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

答案 9 :(得分:1)

要做到这一点而无需依赖任何GNUism,例如不带参数的-i或不带换行符的c

sed '/TEXT_TO_BE_REPLACED/c\
This line is removed by the admin.
' infile > tmpfile && mv tmpfile infile

此命令的形式(符合POSIX)

c\
text

text 可以由一行或多行组成,必须换行的换行符必须转义:

c\
line1\
line2
s/x/y/

其中s/x/y/是在模式空间已被两行替换后的新sed命令

line1
line2

答案 10 :(得分:1)

该行的内容

替换包含指定字符串的整行

文本文件:

Row: 0 last_time_contacted=0, display_name=Mozart, _id=100, phonebook_bucket_alt=2
Row: 1 last_time_contacted=0, display_name=Bach, _id=101, phonebook_bucket_alt=2

单个字符串:

$ sed 's/.* display_name=\([[:alpha:]]\+\).*/\1/'
output:
100
101

用空格分隔的多个字符串:

$ sed 's/.* display_name=\([[:alpha:]]\+\).* _id=\([[:digit:]]\+\).*/\1 \2/'
output:
Mozart 100
Bach 101

调整正则表达式以满足您的需求

[:alpha]和[:digit:] 是Character Classes and Bracket Expressions

答案 11 :(得分:0)

与上述类似......

sed 's/[A-Za-z0-9]*TEXT_TO_BE_REPLACED.[A-Za-z0-9]*/This line is removed by the admin./'

答案 12 :(得分:0)

以下命令对我有用。哪个正在使用变量

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

答案 13 :(得分:-1)

我经常使用正则表达式从我刚刚使用的文件中提取数据,用\"替换文字引用// :-)

cat file.csv | egrep '^\"([0-9]{1,3}\.[0-9]{1,3}\.)' | sed  s/\"//g  | cut -d, -f1 > list.txt