我有一个文本文件,其中有一个特殊行,例如

sometext sometext sometext TEXT_TO_BE_REPLACED sometext sometext sometext


我需要将上面的整行替换为
>
搜索关键字是TEXT_TO_BE_REPLACED

我需要为此编写一个shell脚本。如何使用sed实现此目的?

#1 楼

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

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


评论


请注意,在c \之前需要一个空格。我刚刚进行了编辑以添加此内容。

–马库斯·唐宁(Marcus Downing)
2014年3月17日在12:58

@MarcusDowning GNU sed不需要空格;它可以像最初发布的一样正常工作。如果您的特定sed需要空格,则一定要注意哪个sed不兼容,并添加必要的调用作为注释。但是,请不要在可接受的答案中更改工作代码。

–托德·雅各布斯(Todd A. Jacobs)
2014年3月17日14:08



如何使用变量代替文本“ This ...”?如果我将其替换为$ variable,它不会显示其内容,但会显示变量名称。

–史蒂文
2014年11月26日下午16:47

直接在变量后面跟随c \时存在问题:…c \ $ VAR ...反斜杠将转义美元。在这种情况下,我(在Ubuntu 15.10上使用bash / sed)必须编写…c \\ $ VAR…

– Jan
2015年11月9日在9:45



在Mac上使用:sed -i'''/ TEXT_TO_BE_REPLACED / c \此行已由管理员删除。 / tmp / foo; (当第一个参数为空时,它将编辑文件中的文件,否则创建备份)

– AndreDurao
18年4月10日在11:19

#2 楼

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

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


评论


谢谢,让我的工作正常了:sed's /.* <表达式>。* / <表达式> SE_LABEL = ABC <表达式> / g'MYR2.xml> test.txt

– Nasri Najib
14-10-24在7:46



这可以在Mac OS X Yosemite上工作,但我使用-i和-e标志的情况如下:sed -i -e“ s /.* search_string。* / Replacement_line /'file_being_searched.txt

–肯特·布尔
2014-12-27 19:24



@KentJohnson我认为您的命令中的引号不匹配。

–哈希危害
15年8月12日在16:34

@MBarnett你是对的,我应该在这里用两个双引号引起来。

–肯特·布尔
2015年9月5日,下午1:25

仅提供完整信息。要使其就位,可以添加-i选项

– Temak
2015年11月5日,12:20

#3 楼

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


我的sed版本不喜欢扩展长度为零的-i
c\命令的语法很奇怪,并且我无法使它正常工作
我没有意识到我的某些问题来自未转义的斜杠

所以这是我想出的解决方案,我认为该解决方案最适合案例:

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/
}


因此使用样本来解决所提出的问题:

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


#4 楼

上面的答案:

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


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

问题是在Redhat 5上,\之后的c逃脱了$。双\也不起作用(至少在Redhat 5上有效)。

通过反复尝试,我发现如果替换字符串/行仅是一行,则\之后的c是多余的。因此,我在\之后没有使用c,而是将变量用作单个替换行,这很令人高兴。

代码类似于:

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


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

评论


您仍然可以像这样使用单引号:sed -i'/ TEXT_TO_BE_REPLACED / c'“ $ VARIABLE”“ / tmp / foo

–阿利斯泰尔·麦金太尔(Alistair McIntyre)
19 Mar 4 '19 at 13:20



此变体适用于Ubuntu / Debian:sed -i“ / TEXT_TO_BE_REPLACED / c \\ $ REPLACEMENT_TEXT_STRING” / tmp / foo

–杰西·尼克尔斯(Jesse Nickles)
20年7月25日在11:59

#5 楼

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

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

< pre class =“ lang-bash prettyprint-override”> # 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/'

#6 楼

用于操纵配置文件的方法

我想出了这个受skensell启发的解决方案。 >
如果不存在则创建文件
替换searchPattern匹配的整行(所有行)
如果找不到模式,则在文件末尾添加replaceLine

功能:

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
}


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

#7 楼

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 楼

在我的makefile文件中,我使用以下命令:还要更改模式以替换。
示例输出: “修订:1190”显然与您将它们定义为“修订:”不同...

#9 楼

cat find_replace | while read pattern replacement ; do
sed -i "/${pattern}/c ${replacement}" file    
done 
find_replace文件包含2列,c1带有要匹配的模式,c2带有替换,sed循环替换每一行,其中包含变量1的模式之一

评论


不,这在很多方面都是错误的。使用包含您要执行的所有替换的脚本文件运行sed一次。在同一文件上重复运行sed -i是一个可怕的反模式。

–tripleee
18/12/12在6:46



#10 楼

为此,无需依赖任何GNUism,例如-i不带参数或c不带换行符:
 sed '/TEXT_TO_BE_REPLACED/c\
This line is removed by the admin.
' infile > tmpfile && mv tmpfile infile
 

命令形式)
c\
text

text可以由一行或多行组成,必须转义应成为替换内容的换行符:
 c\
line1\
line2
s/x/y/
 

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


#11 楼

将包含指定字符串的整行替换为该行的内容
文本文件:
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:]]\+\).*//'
output:
100
101

多个由空格分隔的字符串:
$ sed 's/.* display_name=\([[:alpha:]]\+\).* _id=\([[:digit:]]\+\).*/ /'
output:
Mozart 100
Bach 101

调整正则表达式以满足您的需求
[:alpha]和[:digit:]
是字符类和括号表达式

#12 楼

与上面的类似。

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


评论


将FOO = TEXT_TO_BE_REPLACED更改为FOO =此行...因此不符合规范。

–詹斯
13年5月30日在9:18



是的。我们的要求是将整个行替换为“该行已被管理员删除”。如果找到密钥模式“ TEXT_TO_BE_REPLACED”。上面的命令令人满意。如果我的理解是错误的,请纠正我。

– Anapureddy Hari
2013年6月6日14:20



@AnnapureddyHari如果搜索字符串之前或之后的文本中除了A-Za-z0-9之外还包含其他任何内容,则此答案不起作用。正如詹斯指出的那样,如果存在等号则失败。 “ FOO =”部分将保留;您尚未替换整行。该代码是关于文件中可能存在的内容的短视记录。如果您的意思是通配符,则应输入通配符,如Thor的答案所示。

–msouth
16年5月7日在21:37

#13 楼

下面的命令为我工作。正在使用变量

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


评论


但是我的新要求是在替换时对SKIP注释(以#开头)行。当我们替换完整行时,这也将替换注释行,并且您最终将获得重复的属性。如果有人对此有解决方案,请告诉我。

–Ritesh Borkar
19-09-19在9:24



您所说的“重复属性”是什么意思?要取消匹配您使用的地址!地址。

–拉吉布
20-10-26在15:50

#14 楼

我经常使用正则表达式从文件中提取数据,而我只是用正则表达式用\"代替文字引号//什么都没有:-)

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