Chèn một dòng ở số dòng cụ thể với sed hoặc awk


146

Tôi có một tập tin kịch bản mà tôi cần sửa đổi với một tập lệnh khác để chèn một văn bản ở dòng thứ 8.

Chuỗi để chèn : Project_Name=sowstest, vào một tệp có tên start.

Tôi đã cố gắng sử dụng awk và sed, nhưng lệnh của tôi đang bị cắt xén.

Câu trả lời:


231
sed -i '8i8 This is Line 8' FILE

chèn vào dòng 8

8 This is Line 8

vào tập tin TẬP TIN

-i thực hiện sửa đổi trực tiếp để tập tin FILE, không xuất ra thiết bị xuất chuẩn, như được đề cập trong các bình luận của glenn jackman.


3
Có, công tắc -i dành riêng cho GNU-sed.
người dùng không xác định

1
Số -i có nghĩa là "sửa đổi tập tin được chỉ định tại chỗ". Chèn so với nối thêm được thực hiện với '8 một cái gì đó' so với '8 một cái gì đó', độc lập với -i-switch.
người dùng không xác định

11
người dùng mac: với homebrew, brew install gnu-sedvà sau đó sử dụng cái này vớigsed
cwd

4
Điều này là siêu hữu ích! Có cách nào để tôi chèn khoảng trắng ở đầu dòng không? Tôi nhận thấy sed không chú ý đến khoảng trắng ban đầu ...
elju

9
@elju: Vâng, che dấu bằng dấu gạch chéo ngược : sed '8i\ 8 This is Line 8' FILE.
người dùng không xác định


19

Hệ điều hành X / macOS / FreeBSD sed

Các -ilá cờ làm việc khác nhau trên hệ điều hành MacOS sedhơn trong GNU sed.

Đây là cách để sử dụng nó trên macOS / OS X:

sed -i '' '8i\
8 This is Line 8' FILE

Xem man 1 sedđể biết thêm.


18

câu trả lời awk

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

@glenn jackman Tôi cần nhập vào #define SERVER@"http://10.35.42.54/ms0.8"một dòng cụ thể. Làm thế nào tôi có thể đạt được điều này?
Nevin Raj Victor

1
Tôi nghĩ rằng Nevin chỉ cần thoát khỏi dấu ngoặc kép trong chuỗi của mình bằng dấu gạch chéo ngược
Chris Koknat

@waLLe, bắt đầu với trang thông tin awk có mô tả hay về cách thức hoạt động của awk. Ở đây, tôi có 2 cặp "điều kiện {hành động}", lần thứ 2 không có điều kiện có nghĩa là hành động được thực hiện cho mỗi bản ghi. Sau khi bạn đọc xong và bạn vẫn còn thắc mắc, hãy cho tôi biết.
glenn jackman

@glennjackman gần như ở đó .. chỉ không nhận được điều này: file> file.new
w411 ngày 3

"Tập tin" đại diện cho tên của tập tin mà awk đang làm việc. >là biểu tượng chuyển hướng shell để đầu ra của awk được lưu trữ trong tệp có tên "file.new".
glenn jackman

16

POSIX sed(và ví dụ như OS X sed, sedbên dưới) yêu cầu iphải được theo sau bởi dấu gạch chéo ngược và dòng mới. Ngoài ra, ít nhất OS X sedkhông bao gồm một dòng mới sau khi văn bản được chèn:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3

Để thay thế một dòng, bạn có thể sử dụng các lệnh c(thay đổi) hoặc s(thay thế) bằng một địa chỉ số:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3

Các lựa chọn thay thế sử dụng awk:

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3

awkdiễn giải dấu gạch chéo ngược trong các biến được truyền với -vnhưng không phải trong các biến được truyền bằng cách sử dụng ENVIRON:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3

Cả hai ENVIRON-vđược xác định bởi POSIX.


7

Giải pháp Perl:

nhanh chóng và hèn hạ:

perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

  • -l loại bỏ các dòng mới và thêm chúng trở lại, loại bỏ sự cần thiết cho "\ n"
  • -p vòng lặp trên tập tin đầu vào, in mọi dòng
  • -e thực thi mã trong dấu ngoặc đơn

$. là số dòng

tương đương với giải pháp awk của @ glenn, sử dụng các đối số được đặt tên:

perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

  • -s cho phép trình phân tích cú pháp đối số thô sơ
  • -- ngăn -n và -s khỏi bị phân tích cú pháp bởi trình phân tích cú pháp đối số perl tiêu chuẩn

đối số lệnh vị trí:

perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

biến môi trường:

setenv n 8 ; setenv s "Project_Name=sowstest"
echo $n ; echo $s
perl -slpe 'print $ENV{s} if $. == $ENV{n}' file

ENV là hàm băm chứa tất cả các biến môi trường

Getopt để phân tích các đối số thành hàm băm% o:

perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

Getopt :: Tên tùy chọn dài và dài hơn

perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

Getopt là giải pháp thư viện tiêu chuẩn được đề xuất.
Điều này có thể là quá mức cần thiết cho các tập lệnh perl một dòng, nhưng nó có thể được thực hiện


2
Kudos nói với bạn Chris đã dành thời gian để giải thích tất cả những điều đó và trình bày nó thật độc đáo, nhưng wow đây là lý do tại sao tôi không thích perl.
rsaw

5

Đối với những người dùng SunOS không phải là GNU, đoạn mã sau sẽ giúp:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^ J được chèn bằng ^ V + ^ J
  • Thêm dòng mới sau '1i.
  • \ PHẢI là nhân vật cuối cùng của dòng.
  • Phần thứ hai của lệnh phải nằm trong một dòng thứ hai.

5

sed -e '8iProject_Name=sowstest' -i start sử dụng GNU sed

Chạy mẫu:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 

Đâu là dấu vết $đến từ dòng 3 sau khi chèn?
jww

Đó là từ -Acờ cat:)
jno

Điều gì nếu chuỗi bạn muốn chèn chứa dấu ngoặc kép, dấu ngoặc đơn, v.v.?
Anentropic

Xem cập nhật cho văn bản trên. Điều đó có nghĩa là, bạn sẽ phải thoát khỏi những ký tự đó khi thích hợp.
jno

0

sed -i "" -e $ '4 a \\ n''Project_Name = sowstest' bắt đầu

  • Dòng này hoạt động tốt trong macOS
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.