2011-07-18 39 views
31

Tôi đang cố gắng thêm một dòng văn bản vào giữa tệp văn bản trong tập lệnh bash. Cụ thể là tôi đang thử thêm một máy chủ tên vào tập tin /etc/resolv.conf của tôi. Khi đứng, resolv.conf trông như thế này:Làm cách nào để thêm dòng văn bản vào giữa tệp bằng bash?

# Generated by NetworkManager 
domain dhcp.example.com 
search dhcp.example.com 
nameserver 10.0.0.1 
nameserver 10.0.0.2 
nameserver 10.0.0.3 

Mục tiêu của tôi là để thêm nameserver 127.0.0.1 trên tất cả các dòng máy chủ tên khác, nhưng dưới bất kỳ văn bản trên đó. Cuối cùng, tôi muốn tệp resol.conf của mình trông giống như sau:

# Generated by NetworkManager 
domain dhcp.example.com 
search dhcp.example.com 
nameserver 127.0.0.1 
nameserver 10.0.0.1 
nameserver 10.0.0.2 
nameserver 10.0.0.3 

Làm thế nào điều này có thể thông qua tập lệnh bash? Đây có phải là một cái gì đó sed hoặc awk có thể làm gì? Hoặc sẽ sáng tạo greping để tái tạo các tập tin được di chuyển tốt nhất của tôi?

Trả lời

34

Đây là một giải pháp sử dụng sed:

$ sed -n 'H;${x;s/^\n//;s/nameserver .*$/nameserver 127.0.0.1\n&/;p;}' resolv.conf 

# Generated by NetworkManager 
domain dhcp.example.com 
search dhcp.example.com 
nameserver 127.0.0.1 
nameserver 10.0.0.1 
nameserver 10.0.0.2 
nameserver 10.0.0.3 

Cách thức hoạt động: thứ nhất, ngăn chặn đầu ra của sed với -n cờ. Sau đó, đối với mỗi dòng, chúng ta thêm dòng vào không gian giữ, tách chúng bằng dòng mới:

H 

Khi chúng tôi đến cuối của tập tin (giải quyết bằng $), chúng tôi di chuyển nội dung của không gian giữ để không gian mẫu:

x 

Nếu dòng đầu tiên trong không gian mẫu trống, chúng tôi sẽ thay thế nó bằng không có gì.

s/^\n// 

Sau đó chúng tôi thay thế dòng đầu tiên bắt đầu với nameserver bởi một dòng chứa nameserver 127.0.0.1, một dòng mới (Phiên bản của bạn sed thể không hỗ trợ \n, trong trường hợp thay thế n với một dòng mới theo nghĩa đen) và dòng gốc (đại diện bởi &):

s/nameserver .*$/nameserver 127.0.0.1\n&/ 

Bây giờ chúng ta chỉ cần in kết quả:

p 
+1

này là rất tốt. Chỉ có điều kỳ lạ là nó thêm một dòng trống ở trên cùng của tập tin mới. Không phải là một vấn đề lớn, nhưng nó gây ra một khoảnh khắc OCD. – PHLAK

+4

Ồ, vâng, bạn đã đúng! Lệnh 'sed -n' H; $ {x; s/^ \ n //; s/nameserver. * \ N/nameserver 127.0.0.1 \ n & /; p;} 'resolv.conf', tuy nhiên, giải quyết điều này vấn đề. Tôi đã thêm 's/^ \ n //' vào lệnh để nó sẽ loại bỏ dòng mới ở đầu nội dung của không gian mẫu. – brandizzi

+0

Tuyệt vời, cảm ơn! – PHLAK

8

awk '/^nameserver/ && !modif { printf("INSERT\n"); modif=1 } {print}'

+0

Giải pháp 'awk' tuyệt vời, có lẽ là giải pháp duy nhất không sao chép toàn bộ tập tin vào bộ nhớ ... – MestreLion

15

Giả sử bạn muốn chèn ngay sau khi dòng search, đây là đơn giản hơn nhiều:

sed -ie '/^search/a nameserver 127.0.0.1' filename 
  • -i: chỉnh sửa tập tin tại chỗ
  • -e: cho phép thực hiện một kịch bản/biểu hiện lệnh bên trong sed
  • a mynewtext: lệnh mà nói với sed để chèn mynewtext văn bản sau khi xuất hiện mẫu
+0

Đó là điều ... dòng tìm kiếm đó có thể hoặc không thể ở đó. Các dòng máy chủ tên luôn luôn ở đó và tôi muốn dòng mới được chèn ngay trước chúng bất kể phần còn lại của nội dung của tệp. – PHLAK

+0

@PHLAK, giải pháp do Jim cung cấp là tốt. Tôi sẽ sửa đổi nó, mặc dù. Chỉ cần thêm một chú thích _special_ để đánh dấu dòng mà công cụ mới được cho là được nhập vào. Ví dụ. một dòng như '# <>' hoặc một cái gì đó. Sau đó, thay vì '/^search /', bạn có thể tìm kiếm '/^# <> $ /', làm cho nó khó có thể khớp với dòng sai hơn. – bitmask

+0

Bạn sẽ sửa đổi điều này (nếu có thể) để sử dụng một dòng từ một tệp khác (giả sử tệp này chỉ có một dòng), thay vì 'nameserver 127.0.0.1'? – Juan

0

Điều này có thể làm việc cho bạn:

sed -e '/nameserver/{x;/./b;x;h;i\nameserver 127.0.0.1' -e '}' resolv.conf 

Hoặc GNU sed:

sed -e '0,/nameserver/{//i\nameserver 127.0.0.1' -e '}' resolv.conf 
0

Dưới đây là một giải pháp Perl:

perl -lne 'if (not $f and /^nameserver/){ print "nameserver 127.0.0.1"; $f=1 }; print' resolv.conf

  • -n vòng quanh mỗi dòng của tập tin đầu vào, không tự động in mỗi dòng

  • -l loại bỏ dòng mới trước khi chế biến, và thêm chúng trở lại sau

  • -e thực thi mã perl

$f được sử dụng như một lá cờ để chỉ ra rằng chuỗi máy chủ tên đã được tìm thấy

Các vấn đề liên quan