특정 줄 번호가 있는 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.

즉, 라인1,6,10, 그리고11각 파일에서 제거됩니다. 이는 난수 배열의 파일에 있는 유일한 줄 번호이기 때문입니다.

그런데 %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 스크립트(모든 후속 인수는 파일 이름임)를 사용하면 작동합니다.


독립 실행형 스크립트를 저장하지 않으려면 한 줄 스크립트로 실행할 수 있습니다.

$ 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" {} +

그런데 왜 이런 일을 하겠습니까? 보기 흉하고 읽고 편집하기가 어렵습니다. 쉘 명령줄에서 스크립트를 편집하고 디버깅하는 것보다 즐겨 사용하는 편집기에서 임시, 일회성 스크립트를 작성하는 것이 더 쉽고 편리합니다.

관련 정보