文字列パターンのすべての出現を、文字列が見つかった順序に応じて文字列に一致する番号に置き換える方法

Nov 25 2020

内部の文字列を検索するbashスクリプトが必要です。文字列<>が見つからない場合は、インデックスカウンターの現在の値(最初は0)に置き換えて、カウンターをインクリメントする必要があります。<>すでに認識している文字列が内部に見つかった場合は、文字列のインデックスを検索して、インデックスに置き換える必要があります。これは複数のファイルにわたって実行する必要があります。つまり、プログラムの起動時にのみ、複数のファイルでパターンが検索されてもカウンターはリセットされません。

file_a.txt:

<abc>
<b>
<c>
<c>
<abc>

file_b.txt:

<c>
<b>

になるはずです

file_a.txt:

0
1
2
2
0

file_b.txt:

2
1

私がこれまでに得たもの:

names=()
for file in folder/*.txt
do
    name=$(sed 's/\<[a-zA-Z]*\> /\1 /' file) for i in "${names[@]}"
    do
        if [ "$i" -eq "$name" ]
        then
            #replace string with index of string in array
        else
            names+=("$name")
        fi
    done
done

編集:問題を単純化するために私が言及しなかったことは、置き換えられるべきパターンがファイル内の唯一のテキストではないということです。つまり、ファイルは次のようになります
。file_a.txt:

123abc<abc>xyz
efg
<b>ah
a<c>
<c>b
c<abc>

file_b.txt:

xyz<c>xyz
xyz<b>xyz

になるはずです

file_a.txt:

123abc0xyz
efg
1ah
a2
2b
c0

file_b.txt:

xyz2xyz
xyz1xyz

ファイルは非常に大きくなる可能性があるため、コピーするのではなく、編集するだけにしてください。これは、フォルダー内のすべてのファイルとサブフォルダー内のファイルに対して実行する必要があります

回答

3 anubhava Nov 25 2020 at 03:10

このawkスクリプトを試すことができます:

mkdir -p tmp

awk 'match($0, /<[^>]+>/) { k = substr($0, RSTART, RLENGTH)
   if (!(k in freq))
      freq[k] = n++
   $0 = substr($0, 1, RSTART-1) freq[k] substr($0, RSTART+RLENGTH) } { print $0 > ("tmp/" FILENAME)
}' file_{a,b}.txt

変更されたファイルはtmp/ディレクトリに保存され、内容を調べた後で元に戻すことができます。

cat tmp/file_a.txt

123abc0xyz
efg
1ah
a2
2b
c0

cat tmp/file_b.txt

xyz2xyz
xyz1xyz