Lặp lại mỗi dòng nhiều lần


17

Muốn có mỗi dòng trong một tệp lặp lại một số lần cố định.

ví dụ: mỗi dòng được lặp lại bốn lần:

a
b
c

trở thành:

a
a
a
a
b
b
b
b
c
c
c
c

Tôi đã thực hiện một số tìm kiếm, và có rất nhiều câu hỏi và câu trả lời dọc theo dòng thực hiện ngược lại, ví dụ: hợp nhất các dòng trùng lặp thành các dòng đơn và có thể một vài về cách nhân đôi các dòng bằng cách in lại chúng.

Thật dễ dàng để làm điều này trong C, nhưng tôi ước tôi biết nhiều hơn về các lệnh gốc để tôi sẽ không phải dùng đến những kiểu ném một lần này mọi lúc.

Câu trả lời:


19
  • Perl:

    perl -ne 'for$i(0..3){print}' file

    và tôi phải thêm bài này được đăng dưới dạng bình luận của @derobert vì nó rất tuyệt:

    perl -ne 'print "$_" x4'
  • awk và các biến thể:

    awk '{for(i=0;i<4;i++)print}' file
  • bash

    while read line; do for i in {1..4}; do echo "$line"; done; done < file

1
awkSẽ forkhông cần niềng răng nếu chỉ có một lệnh lặp lại. Và perlđơn giản hơn nếu bạn sử dụng foreachvòng lặp : for$i(0..3){print}.
manatwork

4
Thay thế perl : perl -ne 'print(($_)x4)'. Ngoài ra, bạn nên trích dẫn $line(bằng tiếng vang) trong phiên bản bash của bạn.
derobert

Trong trường hợp của tôi, tôi cần kết thúc dòng Windows. như đã thấy ở đây có thể đạt được vớiBEGIN { ORS="\r\n" }
The Red Pea

34

Tôi tự hỏi nếu điều này đang biến thành một trận đấu golf :

sed 'p;p;p' 
awk '1;1;1;1' 
perl -lpE 'say;say;say'   # if Paul McCartney and Michael Jackson were hackers...

Giải trình:

pLệnh của sed là in dòng hiện tại. Hành vi mặc định là in dòng hiện tại ngay trước khi chuyển sang dòng tiếp theo (đó là lý do tại sao sed -nphải cho phép bạn tắt nó). Một số seds cũ không có dấu chấm phẩy (tôi nghĩ) vì vậy có thể bạn phải làmsed -e p -e p -e p

Awk làm việc với condition {action}các cặp. Nếu hành động bị bỏ qua, mặc định là in dòng hiện tại nếu điều kiện trả về đúng. Awk, giống như nhiều ngôn ngữ giống như C, coi 1là đúng. (Để đầy đủ, nếu điều kiện bị bỏ qua, hành động sẽ được thực hiện cho mỗi bản ghi.)

Nhiều hàm perl tận dụng biến "mặc định". Lớp lót này tương đương với (trên perl 5.16):

$ perl -MO=Deparse -lpE 'say;say;say'
BEGIN { $/ = "\n"; $\ = "\n"; }
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    say $_;
    say $_;
    say $_;
}
continue {
    die "-p destination: $!\n" unless print $_;
}

1
+1, nếu có, bạn đang chiến thắng :) Chính xác thì 1làm gì trong awk? Viết tắt cho print $0?
terdon

3
Các câu lệnh Awk được tạo thành từ một điều kiện và một khối, hoặc là tùy chọn, nhưng phải có mặt. Điều kiện mặc định là 1(đúng); khối mặc định tương đương với {print}. Vì vậy, câu lệnh 1sẽ có nghĩa là in bộ đệm dòng hiện tại ( {print}). ( {print}{print $0}hầu hết đều giống nhau, qed.)
Arcege

Tôi chưa bao giờ nghe nói về sedviệc không hỗ trợ dấu chấm phẩy như là dấu chấm dứt lệnh; Có thật sự là có một thứ như vậy không?
tự đại diện


4

Bạn có thể làm điều này mà không đòi hỏi sed, perlhoặc awk.

$ for i in `cat <file>` ; do seq <#> <#> | xargs -i -- echo $i ; done

hoặc sử dụng vòng lặp while:

$ while read i ; do seq <#> <#> | xargs -i -- echo $i ; done < <file>

Ví dụ

cho vòng lặp
$ for i in `cat sample.txt` ; do seq 1 3 | xargs -i -- echo $i ; done
a
a
a
b
b
b
c
c
c
trong khi lặp lại
$ while read i; do seq 1 2| xargs -i -- echo $i;done < sample.txt
a
a
b
b
c
c

Tôi nghĩ rằng phiên bản vòng lặp for sẽ phá vỡ bất kỳ dòng nào chứa khoảng trắng, vì vậy vòng lặp while nên được ưu tiên. Mặt khác, +1 vì tôi là một kẻ hút các giải pháp vỏ.
evilsoup

@evilsoup - vâng, có người khác cũng đề cập đến điều này trên một số mã tôi đã đăng trên một câu hỏi và trả lời khác. Tôi nghĩ đó là lợi thế chính của trong khi hết, vòng lặp while có thể chấp nhận được dấu phân cách $ IFS và sẽ phân tách ở cuối dòng trong khi phân tách trên $ IFS.
slm

1

Sử dụng vỏ hoàn toàn:

repeats=4
while read line; do yes $line|head --lines=$repeats; done < infile > outfile

Có ai đó biết làm thế nào để có có coi --helpnhư là một chuỗi thay vì một tùy chọn? [xem xét trường hợp line--helphoặc tùy chọn khác]
user176581

vâng,yes -- --help
don_crissti

Sử dụng yesheadcó nghĩa đây không phải là "vỏ hoàn toàn"
glenn jackman

1

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

sed 'h;:a;s/[^\n]\+/&/4;t;G;ba' file

Sẽ lặp lại mỗi dòng 4 lần.

Hoặc nếu bạn thích:

sed 'h;:a;s/\n/&/3;t;G;ba' file

Nơi bạn lặp lại mỗi dòng 3 lần nữa.


1

Câu trả lời của @potong không hoạt động với các dòng trống, thay \+vào đó *nên sửa nó:

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
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.