入力ファイルの順序で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コマンドはスクリプトを生成し、2番目のコマンドは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

ご覧のとおり、各置換は、1行で個別に混在した特定の単語と一致し、それを混在させない単語に置き換えます。置換が行われると、各置換の後のベアコマンドは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フィールド値に基づいて2つのファイルの行をマージします。両方の入力は共通フィールドに基づいてソートする必要があります。サインアップするときは、混在したファイルの数と単語リストの混在した単語を保持してください。もう混乱した言葉は必要ありません。

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配列にインポートすることです(上記の2つの方法のいずれかでスクランブルされた単語を取得します)。次に、関連付けられた単語のリストは、歪んだ単語と一般的な単語で構成される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

関連情報