Повторіть кожен рядок кілька разів


17

Хочеться, щоб кожен рядок у файлі повторювався фіксовану кількість разів.

наприклад, повторіть кожен рядок чотири рази:

a
b
c

стає:

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

Я здійснив пошук, і є багато запитань і відповідей по лінії виконання зворотного зв'язку, наприклад, об'єднання повторюваних ліній в одиничні рядки, і, можливо, кілька про подвоєння рядків, надрукувавши їх знову.

Це легко зробити в C, але я б хотів, щоб я знав більше про рідні команди, тому мені не доведеться весь час вдаватися до таких видів одноразових викидів.

Відповіді:


19
  • Perl:

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

    і я повинен додати цей, розміщений як коментар @derobert, тому що це просто круто:

    perl -ne 'print "$_" x4'
  • awk та варіанти:

    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
awk«И forне потребує в фігурні дужки , якщо є тільки одна команда , щоб повторити. І perlпростіше , якщо ви використовуєте foreachцикл: for$i(0..3){print}.
манатура

4
Альтернативні Perl: perl -ne 'print(($_)x4)'. Крім того, ви повинні навести цитату $line(у відгомоні) у своїй баш-версії.
дероберт

У моєму випадку мені потрібні були закінчення рядків Windows. як видно тут, можна досягтиBEGIN { ORS="\r\n" }
Червоний горох

34

Цікаво, чи це перетворюється на матч з гольфу :

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

Пояснення:

pКоманда sed - це надрукувати поточний рядок. Типовою поведінкою є друк поточного рядка безпосередньо перед переходом до наступного рядка (саме тому sed -nповинен дозволити вам вимкнути його). У деяких старих наборах немає крапки з комою (я думаю), тому можливо вам доведеться це зробитиsed -e p -e p -e p

Awk працює з condition {action}парами. Якщо дія пропущено, за замовчуванням друкується поточний рядок, якщо умова повертається як істинна. Awk, як і багато мов, схожих на С, трактує 1як правду. (Для повноти, якщо умова пропущена, дія буде виконуватися для кожного запису.)

Багато функцій perl скористаються змінною "за замовчуванням". Цей одношаровий еквівалент (на 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, якщо так, ти виграєш :) Що саме 1робиш у дивовижному стані? Стенограма для print $0?
terdon

3
Заяви Awk складаються з умови та блоку, або вони є необов'язковими, але вони повинні бути присутніми. Умовою за замовчуванням є 1(вірно); блок за замовчуванням еквівалентний {print}. Отже, оператор 1означатиме надрукувати поточний буфер рядків ( {print}). ( {print}і {print $0}здебільшого однакові, qed.)
Арседж

Я ніколи не чув про sedте, що не підтримує крапки з комою як термінали команд; чи справді таке є?
Wildcard


4

Ви можете зробити це без необхідності sed, perlабо awk.

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

або використовуючи цикл час:

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

Приклади

для петлі
$ for i in `cat sample.txt` ; do seq 1 3 | xargs -i -- echo $i ; done
a
a
a
b
b
b
c
c
c
поки петля
$ while read i; do seq 1 2| xargs -i -- echo $i;done < sample.txt
a
a
b
b
c
c

Я думаю, що версія для циклу порушиться на будь-яких рядках, що містять пробіли, тому слід віддавати перевагу циклу while. В іншому випадку +1, оскільки я присмоктуюсь до оболонок.
evilsoup

@evilsoup - так, хтось ще згадав про це, а також у коді, який я розмістив на іншому запитанні та запитаннях. Я думаю, що це головна перевага при переході до, цикл у той час як толерантний до розділювача $ IFS і розділиться в кінці рядка, тоді як для розщеплення на $ IFS.
slm

1

Використання чисто шкаралупи:

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

Хтось знає, як зробити так, щоб вважати --helpрядок замість опції? [розглянемо випадок, коли lineє --helpінший варіант]
user176581

так,yes -- --help
don_crissti

Використання yesта headозначає, що це не "чисто оболонка"
glenn jackman

1

Це може допомогти вам (GNU sed):

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

Повторимо кожен рядок 4 рази.

Або якщо ви віддаєте перевагу:

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

Де ви повторите кожен рядок ще 3 рази.


1

@potong відповіді «s не працює з порожніми рядками, замінюючи \+з *слід виправити:

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.