X~Y 行が満たす条件に対してのみテキスト処理を行います。

X~Y 行が満たす条件に対してのみテキスト処理を行います。

XからYまでの行にのみ表示される重複行を削除し、ファイルを所定の位置に変更するにはどうすればよいですか?

たとえば、10行から20行の重複行のみを削除したい場合です。

答え1

GNUを使用するawk(4.1.0以降のinplace拡張1):

gawk -i /usr/share/awk/inplace.awk '
  NR >= 10 && NR <= 20 {
    if ($0 in seen) next
    seen[$0]
  }
  {print}' ./file

または以下を使用してperl

perl -ni -e 'print if $. < 10 or $. > 20 or !$seen{$_}++' ./file

複数のファイル処理:

gawk -i /usr/share/awk/inplace.awk '
  BEGINFILE{delete seen}
  FNR >= 10 && FNR <= 20 {
    if ($0 in seen) next
    seen[$0]
  }
  {print}' ./*.txt

または以下を使用してperl

perl -ni -e '
  print if $. < 10 or $. > 20 or !$seen{$_}++;
  if (eof) {close ARGV; undef %seen}' ./*.txt

^使用しないでください-i inplace現在の作業ディレクトリから最初に拡張機能をgawkロードしようとすると、誰かがそのディレクトリにマルウェアを植えた可能性があります。システムに付属の拡張プログラムのパスは異なる場合があります。出力を参照してください。inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

答え2

awkあなたの友達です

awk '{
      if(NR>=10 && NR<=20)
      {
        if($0 in record){
         next
        }else{
         print;
         record[$0];
        }
     }
     else{
        print
     }
     }' file > temp && mv temp file

答え3

OPが10〜20行内の重複行を削除する必要がある場合:

sed -i '
    :a; 10,19!b; N; s/\(^\|\n\)\([^\n]*\)\n\(\(.\+\n\|\)\2$\)/\1\3/; ba
       ' file1 file2 ...

答え4

Perlベースの回答に適用されたのと同じトリックを使用してAwkコードを短縮することもでき、結果的に小さくてきれいになります。

awk 'NR < 10 || NR > 20 || !seen[$0]++'
   ^ ^          ^           ^
   | |          |           |
   | \__________\___________\______ no sigil noise
   |
   \_ no options here to remember
      (unless we want that Gawk inplace semantics)

範囲は10行に制限されており、GNU Awkにはとにかく大きな整数があるため、カウンタはオーバーフローしません。

関連情報