입력 파일 순서대로 grep 출력을 생성하는 방법은 무엇입니까?

입력 파일 순서대로 grep 출력을 생성하는 방법은 무엇입니까?

scrambledA.txt내 목록에 다음과 같은 데이터가 있습니다.

efrrsu
aehmmr
aeeglnr
alnors
acflno
aaahmy
aceimru
1469en
aelprsy
cehrry

그리고 wordlistC.txt많은 키-값 쌍을 포함하는 대응은 다음과 같습니다.

...-...
...-...
1469en-ne1469
aaahmy-yamaha
aceimru-maurice
acflno-falcon
aeeglnr-general
aehmmr-hammer
aelprsy-players
alnors-larson
cehrry-cherry
efrrsu-surfer
...-...
...-...

scrambledA.txtmy 를 의 올바른 단어와 일치시키려고 합니다 wordlistC.txt. 먼저 시도했습니다

grep -f scrambledA.txt wordlistC.txt | cut -d'-' -f2

scrambledA.txt하지만 필요한 순서대로 출력이 제공되지 않습니다. 그런 다음 for 루프를 사용하여 뭔가를 해야 한다고 생각했지만 작동하게 할 수 없었습니다. 내가 뭘 잘못하고 있는 걸까요?

for line in $(cat "scrambledA.txt")
do
    #grep -f "$line" wordlistC >> scrambledBB.txt
    #echo $line | grep -f wordlistC.txt >> scrambledBBB.txt
done

예상 출력은 다음과 같습니다.

surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry

답변1

엄밀히 말하면 당신은입력 파일에 나타나는 순서대로 단어를 가져옵니다. 단지 "입력 파일"이 grep섞인 단어 목록이 아닌 단어 목록 파일 이라는 것뿐입니다 .

grep현재 옵션 과 함께 제공하는 것은 -f섞인 단어 목록이지만 실제로 일치시키려는 패턴은 아닙니다. 일치시키려는 패턴은 단어 목록 파일의 키( -각 줄의 첫 번째 문자열 앞의 문자열)입니다. 당신은 일치하고 싶어그것들스크램블된 파일의 단어를 비교하여 해당하는 스크램블되지 않은 문자열을 찾아냅니다.

awk단어 목록을 연관 배열로 읽은 다음 해당 배열의 잘못된 파일에서 각 줄에 대해 읽은 단어를 찾으면 이 작업을 상당히 쉽게 수행할 수 있습니다 .

$ awk -F - '!wordlist_processed { dict[$1]=$2; next }
            { print $0 in dict ? dict[$0] : "UNKNOWN WORD" }
           ' wordlistC.txt wordlist_processed=1 scrambledA.txt
surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry

UNKNOWN WORD또한 단어 목록에 키로 표시되지 않는 뒤섞인 단어의 문자열도 추가로 인쇄합니다.

완전히 다른 접근 방식은 단어 목록을 스크립트로 변환 sed하고 입력의 단어를 바꾸는 것입니다.

$ sed 's,\([^-]*\)-\(.*\),s/^\1$/\2/;t,' wordlistC.txt | sed -f /dev/stdin scrambledA.txt
surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry

첫 번째 sed명령은 스크립트를 생성하고 두 번째 명령은 sed이를 스크램블된 단어에 적용합니다. 질문의 예( ...-entries 제거됨)를 고려하면 스크립트는 다음과 같습니다.

s/^1469en$/ne1469/;t
s/^aaahmy$/yamaha/;t
s/^aceimru$/maurice/;t
s/^acflno$/falcon/;t
s/^aeeglnr$/general/;t
s/^aehmmr$/hammer/;t
s/^aelprsy$/players/;t
s/^alnors$/larson/;t
s/^cehrry$/cherry/;t
s/^efrrsu$/surfer/;t

(단어 목록의 단어를 있는 그대로 사용하고 있습니다. 즉, 키는 올바른 정규식이어야 하며, 뒤섞이지 않은 단어는 바꾸기 명령의 오른쪽에 포함되기 위해 유효해야 합니다 sed.)

보시다시피, 각 교체는 한 줄에서 개별적으로 뒤섞인 특정 단어와 일치하고 이를 뒤섞이지 않은 단어로 바꿉니다. 대체가 이루어지면 각 대체 이후의 베어 명령은 t스크립트 끝으로 분기됩니다. 이는 입력 라인에서 여러 대체를 방지하기 위한 것입니다.

위의 두 가지 방법 모두 해독하기 위해 뒤섞인 단어에 "단어 목록을 적용"합니다. 그 반대가 아니라 그것이 귀하의 질문에서하는 일입니다.

답변2

wordlistC.txt메모리로 완전히 읽을 수 있으면 scrambledA.txt다음을 사용하여 콘텐츠를 해독 할 수 있습니다 awk.

awk -F'-' '
    # Save lookup key/value
    FNR==NR { w[$1]=$2 }

    # Lookup or error
    FNR<NR { if($1 in w) { print w[$1] } else { print "Unknown:", $1 } }
' wordlistC.txt scrambledA.txt

산출

surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry

답변3

목록의 순서를 유지해야 하는 일반적인 기술은 다음과 같습니다.번호 추가처리하기 전에 처리하십시오. 이 번호를 보관하고 사용하도록 준비유형처리 후 가능합니다.자르다숫자가 나왔습니다.

nl scrambledA.txt | … | sort -k1n | cut -f2

당신은 그것을 사용할 수 있습니다join필드 값을 기준으로 두 파일의 줄을 병합합니다. 두 입력 모두 공통 필드를 기준으로 정렬되어야 합니다. 가입할 때 뒤섞인 파일의 숫자와 단어 목록의 뒤섞인 단어를 유지하세요. 더 이상 뒤섞인 단어가 필요하지 않습니다.

nl scrambledA.txt | sort -k2 |
join -t $'\t' -1 2 -2 1 -o 1.1,2.2 - <(<wordlistC.txt tr - \\t | sort) |
sort -t $'\t' -k1n | cut -f2

답변4

사용행복하다(이전 Perl_6)

#taking scrambledA.txt inline:

~$ raku -ne 'BEGIN my @scrambled = <efrrsu aehmmr aeeglnr alnors acflno aaahmy aceimru 1469en aelprsy cehrry>; 
               state %hash; 
               %hash.append: $_.split("-"); 
             END put %hash{$_} // next for @scrambled;'  wordlistC.txt

또는:

#taking scrambledA.txt using a filepath:

~$ raku -ne 'BEGIN my @scrambled = "/path/to/scrambledA.txt".IO.lines; 
               state %hash; 
               %hash.append: $_.split("-"); 
             END put %hash{$_} // next for @scrambled;'  wordlistC.txt

위 내용은 Perl 계열의 프로그래밍 언어인 Raku로 작성된 답변입니다. Raku는 -ne비자동 인쇄( 비슷한) 줄별 명령줄 플래그를 사용하여 awk호출됩니다 .

Perl과 마찬가지로 Raku에는 해시(예: 연관 배열/사전)가 내장되어 있습니다. 위에서 사용된 전략은 @원하는 출력 순서를 유지하기 위해 스크램블된 단어를 -sigiled 배열로 가져오는 것입니다(위의 두 가지 방법 중 하나로 스크램블된 단어를 가져옵니다). 그런 다음 연관 단어 목록은 왜곡된 단어 와 일반 단어 로 구성된 split하나를 만드는 것 입니다 .%hashkeyvalue

END마지막으로 블록 에서 @scrambled배열을 반복합니다 for. 해시를 해시하여 각 요소(키)를 찾고, %hash{$_}발견되면 해당 값을 출력합니다.value

입력 예(scrambledA.txt):

efrrsu
aehmmr
aeeglnr
alnors
acflno
aaahmy
aceimru
1469en
aelprsy
cehrry

입력 예(wordlistC.txt):

1469en-ne1469
aaahmy-yamaha
aceimru-maurice
acflno-falcon
aeeglnr-general
aehmmr-hammer
aelprsy-players
alnors-larson
cehrry-cherry
efrrsu-surfer

예제 출력:

surfer
hammer
general
larson
falcon
yamaha
maurice
ne1469
players
cherry

wordlistC.txt파일에서 찾을 수 없는 순서가 잘못된 단어를 건너뛰려면 (정의 또는 다음)을 사용하세요 . // next단지 일치 항목을 반환하는 대신 정의 또는 연산자의 오른쪽을 (빈 문자열)로 변경하여 일치하지 않는 항목에 대해 빈 줄을 남겨둘 수 있습니다 . 그렇지 않고 더 자세한 피드백을 원할 경우 다음과 같이 원하는 문자열을 추가하세요.next//""

END put %hash{$_} // "Unknown: $_" for @scrambled;`

https://docs.raku.org/언어/hashmap#Hashes_and_maps
https://docs.raku.org/
https://raku.org

관련 정보