sed-用文件内容替换字符串


22

我有两个文件:file1file2

file1 具有以下内容:

---
  host: "localhost"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "localhost:2181"

file2包含IP地址(1.1.1.1

我想做的是替换localhost1.1.1.1,这样最终结果是:

---
  host: "1.1.1.1"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "1.1.1.1:2181"

我试过了:

sed -i -e "/localhost/r file2" -e "/localhost/d" file1
sed '/localhost/r file2' file1 |sed '/localhost/d'
sed -e '/localhost/r file2' -e "s///" file1

但是我要么更换了整条线,要么将IP移到了我需要修改的那条线之后。


1
不确定,但是cat file1 | sed -e 's/localhost/1.1.1.1/g'行得通吗?
dchirikov 2014年

1
查看\rsed命令。
凯文(Kevin)

Answers:


14

这是一个sed解决方案:

% sed -e "s/localhost/$(sed 's:/:\\/:g' file2)/" file1
---
  host: "1.1.1.1"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "1.1.1.1:2181"

您应该sed -i用来进行更改。

如果可以使用awk,这是一种方法:

% awk 'BEGIN{getline l < "file2"}/localhost/{gsub("localhost",l)}1' file1
---
  host: "1.1.1.1"
  port: 3000
  reporter_type: "zookeeper"
  zk_hosts: 
    - "1.1.1.1:2181"

4
为+1 awk。我想sed 能力做到这一点,但这将非常笨拙。这就是awk光芒!
HalosGhost 2014年

1
@HalosGhost:看来我和您都误解了OP问题,我更新了答案。
cuonglm

sed如果文件包含空格或glob字符,则应使用双引号将解决方案替换为命令。
Graeme 2014年

@Graeme:谢谢,更新!随时进行编辑。
cuonglm

2
您需要同时逃避/&替换。那是"$(sed 's:[/\\&]:\\&:g' file2)"
Toby Speight

6

您可以在使用之前使用shell命令替换来读取带有替换字符串的文件sed。因此,sed将仅看到正常替换:

sed "s/localhost/$(cat file2)/" file1 > changed.txt


18
这对多行文件和特殊字符文件有效吗?
Trevor Hickey

9
@TrevorHickey不是。Sed只是失败,并显示“未终止的s命令”错误。
DarioP

1

尝试使用

join file1 file2

然后,删除所有不需要的字段。


1

我今天也遇到了这个“问题”:如何用另一个文件中的内容替换文本块。

我已经通过创建bash函数(可以在脚本中重用)解决了它。

[cent@pcmk-1 tmp]$ cat the_function.sh
# This function reads text from stdin, and substitutes a *BLOCK* with the contents from a FILE, and outputs to stdout
# The BLOCK is indicated with BLOCK_StartRegexp and BLOCK_EndRegexp
#
# Usage:
#    seq 100 110 | substitute_BLOCK_with_FILEcontents '^102' '^104' /tmp/FileWithContents > /tmp/result.txt
function substitute_BLOCK_with_FILEcontents {
  local BLOCK_StartRegexp="${1}"
  local BLOCK_EndRegexp="${2}"
  local FILE="${3}"
  sed -e "/${BLOCK_EndRegexp}/a ___tmpMark___" -e "/${BLOCK_StartRegexp}/,/${BLOCK_EndRegexp}/d" | sed -e "/___tmpMark___/r ${FILE}" -e '/___tmpMark___/d'
}

[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$ cat /tmp/FileWithContents
We have deleted everyhing between lines 102 and 104 and
replaced with this text, which was read from a file
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$ source the_function.sh
[cent@pcmk-1 tmp]$ seq 100 110 | substitute_BLOCK_with_FILEcontents '^102' '^104' /tmp/FileWithContents > /tmp/result.txt
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$
[cent@pcmk-1 tmp]$ cat /tmp/result.txt
100
101
We have deleted everyhing between lines 102 and 104 and
replaced with this text, which was read from a file
105
106
107
108
109
110
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.