두 개의 특정 위치에 있는 여러 파일의 여러 교체 중 하나를 수행합니다.

두 개의 특정 위치에 있는 여러 파일의 여러 교체 중 하나를 수행합니다.

약 10만 개의 파일이 있고 각 파일에 대해 다음을 수행하고 싶습니다.

다음 ASCII 코드를 포함하는 파일의 다섯 번째 문자와 여섯 번째 문자 사이에 0x1f문자열이 있습니다 . 이제 애플리케이션이 모든 교체 목록이 포함된 특정 파일을 열도록 하고 싶습니다. 나중에 이 교체 파일의 형식을 참조하세요. 대체 항목이 파일에 없는 경우 파일 이름을 stderr에 기록하면 나중에 파일을 수동으로 수정할 수 있습니다. 이제 ascii 코드의 16~17번째 문자 사이에 0x1f대체할 내용이 다시 나타나게 되는데, 이번에는 해당 필드가 단순히 대체할 내용이 아니라 대체할 내용을 담은 html 문자열로 대체할 수 있습니다. 한 번 또는 여러 번. 필드의 첫 번째 항목만 바꾸고 싶습니다.

대체 파일의 형식은 매우 간단합니다. 각 대체 항목은 한 줄에 공백으로 구분되어 있습니다. 교체되는 길이에 따라 정렬됩니다.


대체 파일:

CCCC 3
BCC 233
CCA 331
CCB 332
ACC 133
AA 11
AB 12
BA 21
BB 22
CC 33
A 1
B 2

위와 같은 문자와 숫자가 반드시 포함되어야 한다는 보장은 없습니다. 이는 단지 예시일 뿐이며 UTF-8이 포함될 수 있습니다.

파일: (0x1f 문자는 다음 예에서 ^_로 기록됩니다.)

field1^_field2^_field3^_field4^_field5^_BB^_field7^_hai
this field contains a newline^_some UTF-8オイ^_the next field is empty^_^_
another newline^_field14^_field15^_<b>BB</b>stuff BB^_the previous field contains something to replace^_^_^_more fields...

파일은 다음과 같습니다.

field1^_field2^_field3^_field4^_field5^_22^_field7^_hai
this field contains a newline^_some UTF-8オイ^_the next field is empty^_^_
another newline^_field14^_field15^_<b>22</b>stuff BB^_the previous field contains something to replace^_^_^_more fields...

내 입력의 실제 예를 업로드했습니다.여기. 이 파일의 원하는 출력은 다음과 같습니다.여기( RYO로 대체되어야 함 リョ).


약간의 배경
일부 바보는 데이터베이스에 별도의 열을 생성하지 않고 대신 단일 열을 생성하고 필드를 0x1f 문자로 구분하기로 결정했습니다. 그는 또한 내가 변경하고 싶은 정보를 두 가지 다른 분야에 복사하는 것이 가능할 것이라고 생각했습니다. 데이터베이스의 정보를 pr 파일로 추출합니다. 행에는 필드가 있는 열만 포함되어 있기 때문에 작업하기가 더 쉬울 것 같지만 SQLite 데이터베이스에 제공할 수 있는 명령문을 만들 수 있다면 그것도 좋을 것입니다.

답변1

이 Perl 스크립트가 그 일을 해낼 것입니다. 귀하의 예제를 Pastebin에서 테스트했는데 예상대로 작동합니다.

#!/usr/bin/env perl
use strict;

my %k; ## This hash will store the target/replacement pairs
## Read the list of replacements
open(my $r,"$ARGV[0]")||die "Couldn't open replacements list\n";
while(<$r>){
    chomp;
    my @F=split(/\s+/);
    $k{$F[0]}=$F[1]
}
close($r);
$/=undef;

open(my $fh, "$ARGV[1]")||die "Couldn't open input file\n";
while(<$fh>){
    ## Read the entire file at once
    $/=undef;
    my @F=split(/\x1f/);
    ## If this exists in the replacements list
    if (defined($k{$F[5]})) {
        ## Modify the 17th field. This will only replace the first
        ## occurence. Use 's///g' for all. 
        $F[16]=~s/$F[5]/$k{$F[5]}/;
        ## Replace the 6th field
        $F[5]=$k{$F[5]};

    }
    ## If it doesn't
    else {
        ## Print the file name to STDERR unless the 5th field
        ## was empty.
        print STDERR "Problematic file: $ARGV[1]\n" unless $F[5]=~/^\s*$/;
    }
    ## print each field separated by '0x1f' again.
    print join "\x1f",@F;


}
close($fh);

이를 fixidiocy.pl귀하의 $HOME디렉토리와 cd대상 파일이 포함된 디렉토리에 저장하십시오. 이제 각 파일에서 이를 실행하여 대체 파일의 파일 이름과 경로를 인수로 제공합니다.

for file in *; do 
    perl ~/fixidiocy.pl /path/to/replacements "$file" > "$file".fixed
done

관련 정보