sed - thay thế chuỗi với nội dung tập tin


21

Tôi có hai tập tin: file1file2.

file1 có nội dung như sau:

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

file2chứa địa chỉ IP ( 1.1.1.1)

Những gì tôi muốn làm là thay thế localhostbằng 1.1.1.1, để kết quả cuối cùng là:

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

Tôi đã thử:

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

Nhưng tôi có thể thay thế toàn bộ dòng hoặc IP sẽ chuyển sang dòng sau khi tôi cần sửa đổi.


1
không chắc chắn, nhưng cat file1 | sed -e 's/localhost/1.1.1.1/g'làm việc?
dchirikov

1
Nhìn vào \rlệnh sed.
Kevin

Câu trả lời:


14

Đây là một sedgiải pháp:

% 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"

Bạn nên sử dụng sed -iđể thực hiện thay đổi tại chỗ.

Nếu bạn có thể sử dụng awk, đây là một cách để làm:

% 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 cho awk. Tôi tưởng tượng sed có khả năng này, nhưng nó sẽ được terribly vụng về. Đây là nơi awktỏa sáng!
HalosGhost

1
@HalosGhost: Có vẻ như cả tôi và bạn đều hiểu sai câu hỏi của OP, tôi đã cập nhật câu trả lời của mình.
cuonglm

Thay thế lệnh cho sedgiải pháp nên được trích dẫn gấp đôi trong trường hợp tệp chứa khoảng trắng hoặc ký tự toàn cục.
Graeme

@Graeme: Cảm ơn, đã cập nhật! Hãy thoải mái thực hiện một chỉnh sửa.
cuonglm

2
Bạn cần phải thoát khỏi cả hai /&trong sự thay thế. Đó là"$(sed 's:[/\\&]:\\&:g' file2)"
Toby Speight

6

Bạn có thể đọc tệp với chuỗi thay thế bằng cách sử dụng thay thế lệnh shell, trước khi sedđược sử dụng. Vì vậy, sedsẽ thấy chỉ là một sự thay thế bình thường:

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


18
Điều này có hoạt động trên các tập tin nhiều dòng và các tập tin với các ký tự đặc biệt?
Trevor Hickey

9
@TrevorHickey thì không. Sed chỉ thất bại với lỗi "lệnh" snterminated `s '.
DarioP

1

Hãy thử sử dụng

join file1 file2

và sau đó, loại bỏ bất kỳ trường không mong muốn.


1

Hôm nay tôi cũng gặp "vấn đề" này: làm thế nào để thay thế một khối văn bản bằng nội dung từ một tệp khác.

Tôi đã giải quyết nó bằng cách tạo một hàm bash (có thể được sử dụng lại trong các tập lệnh).

[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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.