各行を複数回繰り返します


17

ファイル内の各行を一定回数繰り返したいと思います。

たとえば、各行を4回繰り返します。

a
b
c

になる:

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

私はいくつかの検索を行いましたが、逆の行に沿って多くの質問と回答があります。たとえば、重複する行を単一の行にマージしたり、再度印刷して行を2倍にしたりします。

Cでこれを行うのは簡単ですが、ネイティブコマンドについてもっと詳しく知りたいので、このような1回限りのスローアウェイにいつも頼る必要はありません。

回答:


19
  • Perl:

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

    そして、@ derobert がコメントとして投稿したこの1つを追加する必要があります。

    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「S forの繰り返しに一つだけのコマンドがある場合は、中括弧を必要としません。また、loop:perlを使用する方が簡単です。foreachfor$i(0..3){print}
マナトワーク

4
代替のperl: perl -ne 'print(($_)x4)'。また、$linebashバージョンで(エコーで)引用する必要があります。
デロバート

私の場合、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...

説明:

sedのpコマンドは、現在の行を印刷することです。デフォルトの動作では、次の行に移動する直前に現在の行を印刷します(そのため、sed -nでオフにできるようにする必要があります)。いくつかの古いsedにはセミコロンが付いていないので(私は思う)、そうする必要があるかもしれませんsed -e p -e p -e p

Awkはcondition {action}ペアで機能します。アクションが省略された場合、デフォルトでは、条件がtrueを返す場合、現在の行が印刷されます。多くのCライクな言語と同様に、Awk 1はtrueとして扱います。(完全を期すために、条件が省略された場合、アクションは各レコードに対して実行されます。)

多くの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、そうであれば、あなたは勝っている:) 1awkで何をするのか。省略形print $0
テルドン

3
Awkステートメントは条件とブロックで構成され、いずれかはオプションですが、1つ存在する必要があります。デフォルトの条件は1(true)です。デフォルトのブロックはと同等{print}です。したがって、このステートメント1は、現在の行バッファー({print})を印刷することを意味します。({print}そして{print $0}QED、ほとんど同じである。)
Arcege

sedコマンドターミネータとしてセミコロンをサポートしていないを聞いたことはありません。本当にそんなことがありますか?
ワイルドカード


4

あなたは必要とせず、これを行うことができsedperlまたはawk

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

または、whileループを使用します。

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

forループ
$ 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ループ
$ while read i; do seq 1 2| xargs -i -- echo $i;done < sample.txt
a
a
b
b
c
c

forループバージョンは、空白を含むすべての行で中断するため、whileループを優先する必要があります。そうでなければ、私はシェルソリューションの吸盤だから+1。
evilsoup

@evilsoup-はい、他の誰かが私が別のQ&Aに投稿したコードでこれについても言及しました。これは、while over forの主な利点だと思います。whileループは$ IFSセパレーターを許容し、forが$ IFSで分割するのに対し、行末で分割します。
slm

1

純粋なシェルの使用:

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

誰かがイエスを--helpオプションではなく文字列とみなす方法を知っていますか?[ lineis --helpまたは別のオプションの場合を考慮]
user176581

はい、yes -- --help
-don_crissti

を使用してyesheadこれは「純粋なシェル」ではないことを意味します
グレンジャックマン

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の答えは空の行では機能せず、置き換え\+*修正する必要があります:

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.