sed:替换一行的一部分
Posted
技术标签:
【中文标题】sed:替换一行的一部分【英文标题】:sed: Replace part of a line 【发布时间】:2010-11-07 15:35:03 【问题描述】:如何用 sed 替换一行的一部分?
线
DBSERVERNAME xxx
应该替换为:
DBSERVERNAME yyy
值 xxx 可以变化,并且在 dbservername 和值之间有两个选项卡。此名称-值对是配置文件中的许多对之一。
我尝试了以下反向引用:
echo "DBSERVERNAME xxx" | sed -rne 's/\(dbservername\)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'
这导致了一个错误:'s' 命令的 RHS 上的无效引用 \1。
表达式有什么问题?使用 GNU sed。
【问题讨论】:
【参考方案1】:这行得通:
sed -rne 's/(dbservername)\s+\w+/\1 yyy/gip'
(当您使用 -r 选项时,您不必转义括号。)
一点解释:
-r
是扩展的正则表达式 - 改变了正则表达式的编写方式。
-n
除非指定,否则不会打印 - sed
否则默认打印,
-e
表示它后面是一个表达式。让我们分解表达式:
s///
是搜索替换的命令,第一对是要匹配的正则表达式,第二对是替换,
gip
,跟在搜索替换命令之后; g
表示全局,即每个匹配项而不是第一个匹配项将被替换为一行; i
不区分大小写; p
表示完成后打印(记住之前的 -n
标志!),
括号表示匹配部分,稍后会出现。所以dbservername
是第一个匹配部分,
\s
是空格,+
表示出现一次或多次(相对于 *
,零次或多次),
\w
是一个单词,即任何字母、数字或下划线,
\1
是 GNU sed
的一个特殊表达式,它打印伴随搜索中的第一个括号匹配。
【讨论】:
我知道你们在 shell 命令方面有很多经验...但是请尽可能多地关心有抱负的 linux 新手...''
中的所有内容都需要解释...或者我必须经过整个doc
请注意,在模式中使用sed -n
和/p
,这只会打印更改的行(过滤掉文件的其余部分),我不确定这是提问者想要的。 (与 sed -rpe 's/.../.../gi
相比,它会打印每一行,只更改匹配项。)【参考方案2】:
其他人已经提到了括号的转义,但是如果行的第一部分是常量,为什么还需要反向引用呢?
你可以这样做
sed -e 's/dbservername.*$/dbservername yyy/g'
【讨论】:
好点!我刚刚了解了使用 regexps + sed 并且在看到这个特定任务时才决定使用“regexp”,然后正如“jwz”所说“我有两个问题”(尽管不是直接由于 regexps):) 这得到了我的投票,因为它是解决简单问题的最简单方法。使用反向引用可以避免错误输入dbservername
的两个副本。这里很明显,但是当我在 sed 中修改 postgresql.conf 时,我发现很难一眼看出我输入的是 listen_address
还是 listen_addresses
(postgresql.conf)。两者看起来都有道理,但只有一个是正确的。【参考方案3】:
你正在逃避你的 ( 和 )。我很确定你不需要这样做。试试:
sed -rne 's/(dbservername)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'【讨论】:
【参考方案4】:当你使用单引号时,你不应该转义。即。
echo "DBSERVERNAME xxx" | sed -rne 's/(dbservername[[:blank:]]+)([[:alpha:]]+)/\1 yyy/gip'
【讨论】:
【参考方案5】:你不应该逃避你的父母。试试:
echo "DBSERVERNAME xxx" | sed -rne 's/(dbservername)[[:blank:]]+([[:alpha:]]+)/\1 yyy/gip'
【讨论】:
【参考方案6】:这可能对你有用:
echo "DBSERVERNAME xxx" | sed 's/\S*$/yyy/'
DBSERVERNAME yyy
【讨论】:
【参考方案7】:试试这个
sed -re 's/DBSERVERNAME[ \t]*([^\S]+)/\yyy/ig' temp.txt
或者这个
awk 'if($1=="DBSERVERNAME") $2 ="YYY" print $0;' temp.txt
【讨论】:
以上是关于sed:替换一行的一部分的主要内容,如果未能解决你的问题,请参考以下文章