ファイルを分割する: `sed` で `egrep` を置き換える

ファイルを分割する: `sed` で `egrep` を置き換える

私は分割したい$ファイル含むバツ行を半分に分割し、何行に「死んだ」というログを書いてみました。私は次のように書き始めました。

half=`expr $(egrep -c . $file) / 2`

sed -n 1,${half}p $file | 
    xargs echo $file $half $(egrep -c dead $I) > log_1
sed -n ${half},${egrep -c . $file}p | 
    xargs echo $file $half $(egrep -c dead $I) > log_2

最初のsedコマンドの出力は正常ですが、egrep範囲内で代入するとsedエラーが発生します。

DeadOrAlive 5 2
-bash: ${half},${egrep -c . $file}p: bad substitution

ファイルを分割するより効率的な方法はありますかbash?

答え1

  1. wc、および を使用するheadtail:

    half=$(( $(wc -l "$file")/2 ))
    head -$half | egrep -c dead | xargs echo "$file" $half > log_1
    tail -$half | egrep -c dead | xargs echo "$file" $half > log_2
    
  2. 使用方法split:

    split -a1 --numeric-suffixes=1 -n 'l/2' "$file" "$file"_
    echo "$file" "$file"_1 $(egrep -c dead "$file_1") > log_1
    echo "$file" "$file"_2 $(egrep -c dead "$file"_2) > log_2
    rm "$file"_[12]
    

答え2

ここに Awk ソリューションがあります。

awk '/dead/ { a[++n] = NR }
    END { for (i=1; i<=n; i++) if (a[i] > NR/2) break
        print ARGV, int(NR/2), i-1 >"log_1";
        print ARGV, int(NR/2)+(int(NR/2)!=NR/2), n-i+1 >"log_2" }' file

一致した行番号を配列に収集しますa。次に、配列内の行番号のうち、中央の行よりも小さい行がいくつあるかを計算します。その数は最初のパーティションに割り当てられます。(ループから抜けるi-1ときにすでにパーティション分割ポイントを過ぎているため、を使用する必要があります。)break

一般的に、特にファイルが大きい場合は、同じファイルを何度も再読み取りすることは避け、次に、プロセスの数を最小限に抑えるようにしてください。

中間の出力フィールドに何が含まれると予想されるかは明確ではありません。ファイルに奇数の行が含まれている場合、最初の「半分」には 2 番目のパーティションよりも 1 行少ない行が含まれます。(これを変更するのは難しくありませんが、どちらか一方を決定する必要があります。)

関連情報