特定の行番号を持つASCII(.csv)ファイルから一連の行を削除する

特定の行番号を持つASCII(.csv)ファイルから一連の行を削除する

"dir000"、"dir001"などという名前の297のディレクトリがあります。各ディレクトリには、3列と256行のcsvファイル「config」というテキストファイルが含まれています。 1から256までの範囲で25の乱数を生成し、各ディレクトリ内のすべてのファイルから正確に25行を削除する必要があります。たとえば、私のジェネレータが私に乱数範囲を提供している場合は、すべてのa = [145,11,140,119,183,178,225,131,1,65,213,115,207,41,194,221,10,205,6,57,224,108,44,85,211]ディレクトリからこの行を削除したいと思います。 。各ディレクトリにあるASCIIファイル( "config")。誰でもコマンドラインを使ってこれを達成する方法を教えてください。 Ubuntu 16.04ディストリビューションを使用しています。

答え1

Perlの-iオプションを使って、入力ファイルをその場で編集してみましょう。

#!/usr/bin/perl -i

use strict;

# Parse array of random numbers from the first argument.
my $arg1 = shift;
# remove [, ], and any whitespace.
$arg1 =~ s/\[|\]|\s+//g;

# split $arg1 on commas, build an associative array 
# (aka "hash") called %a to hold the numbers.
# The hash keys are the line numbers, and the value for 
# each key is just "1" - it doesn't matter what the
# value is, the only thing that matters is whether the
# key exists in the hash.
my %a;
map $a{$_} = 1, split(/,/, $arg1);

# Loop over each input file.
while (<>) {
  # Print each line unless the current line number $. is in %a.
  print unless defined $a{$.};

  # reset $. at the end of each file.
  close(ARGV) if eof;
}

たとえば、別の名前で保存し、delete-lines.plを使用して実行可能にし、chmod +x delete-lines.pl次のように実行します。

$ a="[145,11,140,119,183,178,225,131,1,65,213,115,207,41,194,221,10,205,6,57,224,108,44,85,211]"
$ ./delete-lines.pl "$a" textfile*.txt

textfile1.txt, textfile2.txt,textfile3.txtともに次の内容を含む場合今後実装する:

I have a series of 297 directories named as "dir000', 'dir001' and so on, each
of which contains a text file called "config", which is a csv file with 3
columns and 256 rows.

I have generated 25 random numbers in the range 1 to 256, and from all these
files in each directory, I am required to remove those exact 25 rows.

For instance, if my generator gave me a series of random numbers a =
[145,11,140,119,183,178,225,131,1,65,213,115,207,41,194,221,10,205,6,57,224,10
8,44,85,211], I want to delete exactly these rows from each of the ASCII
files("config") in each directory.

Can anyone let me know how this can be achieved using command line? I am using
Ubuntu 16.04 distribution.

これにより、すべてこの内容が含まれます。後ろに実装する:

of which contains a text file called "config", which is a csv file with 3
columns and 256 rows.

I have generated 25 random numbers in the range 1 to 256, and from all these

For instance, if my generator gave me a series of random numbers a =
[145,11,140,119,183,178,225,131,1,65,213,115,207,41,194,221,10,205,6,57,224,10

Can anyone let me know how this can be achieved using command line? I am using
Ubuntu 16.04 distribution.

つまり、ライン161011各ファイルから削除されます。これは、乱数配列のファイル内の唯一の行番号であるためです。

ところで、%aハッシュには以下が含まれます。

{
    1 => 1,   6 => 1,  10 => 1,  11 => 1,  41 => 1,
   44 => 1,  57 => 1,  65 => 1,  85 => 1, 108 => 1,
  115 => 1, 119 => 1, 131 => 1, 140 => 1, 145 => 1,
  178 => 1, 183 => 1, 194 => 1, 205 => 1, 207 => 1,
  211 => 1, 213 => 1, 221 => 1, 224 => 1, 225 => 1,
} 

次の手順は、番号付きのディレクトリにある「config」という名前の複数のファイルに対してこれを実行することです。

find dir[0-9]*/ -type f -name config -exec ./delete-lines.pl "$a" {} +

これは、乱数配列がまだシェル変数にあると仮定します$a。必要に応じて別の変数名を使用することも、配列を次のように指定する限り、引用符で囲まれた文字列として指定することもできます。最初perlスクリプト(すべての後続の引数はファイル名です)を使用すると機能します。


スタンドアロンスクリプトを保存したくない場合は、1行スクリプトで実行できます。

$ find dir[0-9]*/ -type f -name config -exec perl -i -e \
    'map $a{$_} = 1, split(/,/, ($ARGV[0] =~ s/\[|\]| +//g, shift));
     while (<>) {print unless defined $a{$.}; close(ARGV) if eof}' \
     "$a" {} +

しかし、なぜこのようなことをしますか?見苦しく、読んで編集するのは難しいです。シェルのコマンドラインでスクリプトを編集してデバッグするよりも、お気に入りのエディタで一時的なワンタイムスクリプトを作成する方が簡単で便利です。

関連情報