Làm cách nào để chèn các dòng có số từ X đến Y vào một tệp khác sau dòng Z?


7

Tôi đã tạo hai tệp:

echo -e "1\n2\n3\n4\n5" > 123.txt
echo -e "a\nb\nc\nd\ne" > abc.txt

Tôi muốn lấy tệp 123.txtcó nội dung sau:

1
2
3
b
c
d
4
5

Vì vậy, nói cách khác, chèn các hàng có số từ 2 đến 4 của tệp abc.txtvào tệp 123.txtsau dòng thứ ba.

Tôi đã xem xét nhiều câu hỏi tương tự ở đây, nhưng không tìm thấy câu trả lời phù hợp. Tuy nhiên, tôi đã nhận được các dòng:

sed -n '2,4p' abc.txt

và đặt một số văn bản vào tệp sau dòng thứ ba:

sed -i '3a\mytext' 123.txt

Làm thế nào để làm điều này bằng cách sử dụng thiết bị xuất chuẩn lệnh trước hoặc / và sed/ awklệnh duy nhất?


Không phải là một giải pháp thanh lịch. Nhưng vẫn có thể được thực hiện như một lệnh duy nhất. head -n +3 123.txt > tmp && cat abc.txt >> tmp && tail -n +2 123.txt >> tmp && mv tmp 123.txt
Ramesh

@Ramesh Tôi đồng ý với bạn. Chỉ sửa lệnh của bạn vì nó cho kết quả sai. head -3 123.txt > tmp && tail -4 abc.txt | head -3 >> tmp && tail -2 123.txt >> tmp && mv tmp 123.txt
Sứ đồ

Câu trả lời:


6

Nếu hệ thống của bạn có phiên bản GNU sed, bạn có thể sử dụng rlệnh mở rộng GNU :

r filename
    As a GNU extension, this command accepts two addresses.

    Queue the contents of filename to be read and inserted into the
    output stream at the end of the current cycle, or when the next input 
    line is read. Note that if filename cannot be read, it is treated as 
    if it were an empty file, without any error indication.

    As a GNU sed extension, the special value /dev/stdin is supported for 
    the file name, which reads the contents of the standard input. 

Ví dụ,

$ sed '3r /dev/stdin' 123.txt < <(sed -n '2,4p' abc.txt)
1
2
3
b
c
d
4
5

2
Các rlệnh là trong POSIX. Điều duy nhất không phải là POSIX (nhưng phổ biến ngay cả trên các hệ thống không phải GNU) trong phần sed là /dev/stdin. Nếu bạn sử dụng đường ống thay vì thay thế lệnh, đoạn mã shell của bạn là POSIX ngoài yêu cầu /dev/stdintồn tại.
Gilles 'SO- ngừng trở nên xấu xa'

Lệnh trả lời cũng cho kết quả mong muốn trên FreeBSD (một hệ thống không phải GNU).
Sứ đồ

3

Bằng cách sử dụng awksed:

$ awk 'FNR==3{print;system("sed -n '2,4p' abc.txt");next};1' 123.txt 
1
2
3
b
c
d
4
5

2

Với sed, bạn có thể sử dụng rlệnh để chèn toàn bộ tệp. Để chèn một phần của tệp, giải nén phần đó và đặt nó làm đầu vào sed. Bạn có thể sử dụng sedđể thực hiện khai thác là tốt.

sed -n '2,4p' abc.txt | sed -i '3r /dev/stdin' 123.txt

Với awk, bạn có thể đọc một tệp và chuyển sang một tệp khác ở giữa.

awk <123.txt >123.txt.new '
    1                                    # print the input line
    NR==3 {                              # after line 3 of 123.txt, …
        while (getline < "abc.txt") {
            ++inner_NR;
            if (inner_NR >= 2) print;    # start printing at line 2 from abc.txt
            if (inner_NR == 4) break;    # stop after line 4
        }
    }
' &&
mv 123.txt.new 123.txt

Bạn cũng có thể sử dụng headtailtrích xuất các phần của tệp mà bạn muốn kết hợp.

head -n 3 <123.txt >123.txt.new &&
<abc.txt tail -n +2 | head -n 3 >>123.txt.new &&
tail -n +4 123.txt >>123.txt.new &&
mv 123.txt.new 123.txt

Bạn có thể kết hợp phương pháp head+ tailvới sed. Đối với các tệp lớn, đây có thể là nhanh nhất.

<abc.txt tail -n +2 | head -n 3 | sed -i '3r /dev/stdin' 123.txt

Lưu ý rằng tất cả các cách tiếp cận này ghi vào một tệp tạm thời được chuyển đến 123.txt(ngay cả các cách tiếp cận đang sử dụng sed -i, bởi vì đó là những gì sed -ithực hiện dưới mui xe).


2

Chỉnh sửa tại chỗ bằng cách sử dụng edsed(trên dấu nhắc bash):

ed -s 123.txt<<<$'3r !sed -n "2,4p" abc.txt\nw'
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.