sed - แทนที่สตริงด้วยเนื้อหาไฟล์


22

ฉันมีสองไฟล์: และfile1file2

file1 มีเนื้อหาดังต่อไปนี้:

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

file2มีที่อยู่ IP ( 1.1.1.1)

สิ่งที่ฉันต้องการจะทำคือแทนที่localhostด้วย1.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

1
ดูที่\rคำสั่ง sed
Kevin

คำตอบ:


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

1
@ HalosGhost: ดูเหมือนว่าฉันและคุณเข้าใจผิดกับคำถาม OP ฉันได้อัปเดตคำตอบของฉัน
cuonglm

การทดแทนคำสั่งสำหรับsedโซลูชันควรถูกยกมาสองครั้งในกรณีที่ไฟล์มีช่องว่างหรืออักขระกลม
แกรม

@ Graeme: ขอบคุณอัปเดต! อย่าลังเลที่จะทำการแก้ไข
cuonglm

2
คุณต้องหลบหนีทั้งใน/และ&ในการเปลี่ยนตัว นั่นคือ"$(sed 's:[/\\&]:\\&:g' file2)"
โทบี้ Speight

6

คุณสามารถอ่านไฟล์ด้วยสตริงการแทนที่โดยใช้การทดแทนคำสั่งเชลล์ก่อนที่จะsedถูกใช้ ดังนั้นsedจะเห็นเพียงการทดแทนปกติ:

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


18
สิ่งนี้ใช้ได้กับไฟล์และไฟล์หลายแถวที่มีอักขระพิเศษหรือไม่
เทรเวอร์ Hickey

9
@ เทรเวอร์มิกกี้มันไม่ได้ Sed เพียงล้มเหลวด้วยข้อผิดพลาด "คำสั่ง` s '"
DarioP


1

ฉันยังมี "ปัญหา" วันนี้: วิธีการแทนที่กลุ่มข้อความด้วยเนื้อหาจากไฟล์อื่น

ฉันแก้ไขมันด้วยการสร้างฟังก์ชั่นทุบตี (ซึ่งสามารถนำมาใช้ซ้ำในสคริปต์)

[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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.