ファイルをそれ自体にn回連結するLinuxコマンド


31

Project Gutenbergからプレーンテキストファイルブック(約0.5 MB)を取得nしました。これをいくつかのアルゴリズムのベンチマークとなる大きなテキストファイルを生成するために、それ自体を時間に連結します。これを達成するために使用できるLinuxコマンドはありますか? cat理想的に聞こえますが、ファイルをそれ自体に連結することであまりうまく機能していないようですn。さらに、質問の時間部分に直接対処していません。


2
何らかのループを使用して、追加しますか?foo.txt >> bar.txtを繰り返して、それを何回もコマンドを実行するものでラップしますか?
ジャーニーマンオタク

回答:


35

これには2つの部分があります。まず-catを使用してテキストファイルを標準出力に出力し、appendを使用して別のファイルに追加します。たとえば、foo.txt >> bar.txtはfoo.txtをbar.txtに追加します

次に、n回実行します

for i in {1..n};do cat foo.txt >> bar.txt; done

そのコマンドのnを自分の番号に置き換えます

動作するはずです。nはあなたの番号です

cshを使用する場合、「繰り返し」コマンドがあります。

回答の関連する部分をここからコピーし、デフォルトのbashシェル上のubuntu 11.04システムでテストしました。


3
楽しい事実:これは実際には 'n'を置き換えることなく機能します。この場合、ASCII '1'とASCII 'n'の間の各文字に対して本体を1回実行します(つまり62回)。しかし{1..12}、ボディを12回正しく実行します。
アーノウエンゲレン

1
あなただけではなく、各反復で追加するよりも、全体のパイプラインをリダイレクトすることがあります:for i in {1..n};do cat foo.txt; done > bar.txt
トビースパイツ

2

私は退屈しているので、ファイルをそれ自体に連結する方法に関するいくつかの方法がありますが、ほとんどheadは松葉杖としてです。私は自分自身について説明しすぎた場合、私は物事を言うのが好きです:P


Nあなたがしたい自己連結の数であり、あなたのファイルが命名されてfileいると仮定します。

変数:

linecount=$(<file wc -l)

total_repeats=$(echo "2^$N - 1" | bc) # obtained through the power of MATH

total_lines=$((linecount*(total_repeats+1)))

tmp=$(mktemp --suffix .concat.self)

コピーを考えるとfile呼ばれるfile2total_repeats回数があるfileために追加される必要があるであろうfile2かのように同じにするためにfile、それ自体に連結されたN回数。

言ったMATHは多かれ少なかれここにある:MATH(要旨)

最初の学期のコンピューターサイエンスですが、帰納的証拠を作成してからしばらくは時間が経ちましたので、それを乗り越えることはできませ2^Loopsん...


POSIX

私はいくつかの非POSIXのものを使用していますが、それらは必須ではありません。私の目的のために:

 yes() { while true; do echo "$1"; done; }

ああ、私はそれだけを使用しました。まあ、セクションはすでにここにあります...


方法


head 行数の追跡。

ln=$linecount
for i in $(seq 1 $N); do
    <file head -n $ln >> file;
    ln=$((ln*2))
done

一時ファイルも猫もありません。まだ数学も多すぎず、すべてが喜びです。


teeMATH

<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file

ここteeからは読み取りが行われますfileが、常に追加されているため、head停止するまで繰り返しファイルを読み取り続けます。そして数学のためいつそれを止めるべきか知っています。追加はオーバーボードになるため、一時ファイルを使用しました。余分な線も切り取ることができますfile


eval、闇の支配者!

eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file

これは単に拡張しcat file file file ...て評価します。$tmpファイルなしでも実行できます。

eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
  head -n $((total_lines-linecount)) >> file

2番目のhead「トリック」はcat、それと書き込み操作の間に中間者を置きます。cat別の人catをだますこともできますが、動作に一貫性がありません。これを試して:

test_double_cat() {
    local Expected=0
    local Got=0
    local R=0
    local file="$(mktemp --suffix .double.cat)"
    for i in $(seq 1 100); do

        printf "" > $file
        echo "1" >> $file
        echo "2" >> $file
        echo "3" >> $file

        Expected=$((3*$(<file wc -l)))

        cat $file $file | cat >> $file

        Got=$(<file wc -l)

        [ "$Expected" = "$Got" ] && R="$((R+1))"
    done
    echo "Got it right $R/100"
    rm $file
}

sed

<file tr '\n' '\0' |
    sed -e "s/.*/$(yes '\0' | head -n $total_repeats | tr -d '\n')/g" |
        tr '\0' '\n' >> file

sedファイル全体を強制的に行として読み取り、すべてをキャプチャしてから、$total_repeats何度も貼り付けます。

ファイルにヌル文字が含まれている場合、これはもちろん失敗します。あなたがそこにないことを知っているものを選んでください。

find_missing_char() {
  local file="${1:-/dev/stdin}"

  firstbyte="$(<$file fold -w1 | od -An -tuC | sort -un | head -n 1)"
  if [ ! "$firstbyte" = "0" ]; then
    echo "\0"
  else
    printf "\\$(printf '%03o\t' $((firstbyte-1)) )"
  fi
}

これですべてです。このarbitrary意的な答えが誰にも邪魔されないことを願っています。私はそれらすべてを何度もテストしましたが、私はたった2年のシェルユーザーですので、覚えておいてください。寝る...

rm $tmp


2

あなたは確かcatにこれに使用できます:

$ cat /tmp/f
foo
$ cat /tmp/foo /tmp/f
foo
foo

$nコピーを取得するには、次の場所にyesパイプ接続しhead -n $nます。

$ yes /tmp/f | head -n 10
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f

それをまとめると

yes /tmp/f | head -n $n | xargs cat >/tmp/output
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.