awkを使用してHTMLファイルを置き換える

awkを使用してHTMLファイルを置き換える

私のawkスクリプトはでレコードを読み取り、file1で同じレコードを見つけて、file2(レコード内の)置換位置をここで定義されたシンボルに置き換えます。しかし、期待どおりに置き換えられない値はほとんどありません。単語の最初のインスタンスのみが置き換えられます。

  • TYTYTY入力するT##Y##
  • TYTYTYGGHG入力するT##Y##GGHG
  • LEFT入力するL##T
  • LEFT NAME入力するL##T NAME

予想される出力は次のとおりです。

私のコード -

awk ' FNR==NR
{
if ($0 in word)
next
word[$0]=$0
for (i=1;i<=NF;i++)
 {
   old=$i
   new=""
   while (old) {
         len=length(old)
         new=new substr(old,1,1) substr("##",1,len-1)
         old=substr(old,4)
       }
      id=index(word[$0],$i)
      word[$0]=substr(word[$0],1,id-1) new substr(word[$0],id+length($i))
  }
 next
}

{
 for (i in word)
 {
  regex = "\\<" i "\\>"
  gsub(regex, ext[i])
  #id=index($0,i)
  #while(id>0) {
  #$0=substr($0,1,id-1) word[i] substr($0,id+length(word[i])) 
  #id=index($0,i)
 }
}
print 
}' records test.html > output.html
$ cat records

LEFT NAME
LEFT NAME 2
LEFT 
LEFT 123
TYTYTYGGHG
TYTYTY    
AB 8263
AB SCENARIO DEBUG
AB 8263 SCENARIO DEBUG

$cattest.html

<html>
<body>
<hr><br><>span class="table">TabA</span><table>
<tr class="column">
 <td>LEFT NAME</td>
 <td>LEFT</td>
 <td></td>
 <td>LEFT NAME 2</td>
 <td>LEFT 123</td>
 <td>TYTYTYGGHG</td>
 <td></td>
 <td>TYTYTY</td>
</tr>
<tr class="data">
<td></td>
<td></td>
<td></td>
<td>AB 8263</td>
<td></td>
<td></td>
<td>AB SCENARIO DEBUG</td>
<td>AB 8263 SCENARIO DEBUG</td>
</tr>
</table>
</body>
</html>

必要なアクション -

<html>
<body>
<hr><br><>span class="table">TabA</span><table>
<tr class="column">
 <td>L##T N##E</td>
 <td>L##T</td>
 <td></td>
 <td>L##T N##E 2</td>
 <td>L##T 1##</td>
 <td>T##Y##G##G</td>
 <td></td>
 <td>T##Y##</td>
</tr>
<tr class="data">
<td></td>
<td></td>
<td></td>
<td>A# 8##3</td>
<td></td>
<td></td>
<td>A# S##N##I# D##U#</td>
<td>A# 8##3 S##N##I# D##U#</td>
</tr>
</table>
</body>
</html>

電流出力 -

<html>
<body>
<hr><br><>span class="table">TabA</span><table>
<tr class="column">
 <td>L##T NAME</td>
 <td>L##T</td>
 <td></td>
 <td>L##T NAME 2</td>
 <td>L##T 123</td>
 <td>T##Y##GGHG</td>
 <td></td>
 <td>T##Y##</td>
</tr>
<tr class="data">
<td></td>
<td></td>
<td></td>
<td>A# 8##3</td>
<td></td>
<td></td>
<td>A# S##N##I# D##U#</td>
<td>A# 8##3 SCENARIO DEBUG</td>
</tr>
</table>
</body>
</html>

ベストアンサー1

それでもこれは詐欺ではありません。https://stackoverflow.com/questions/34375020/why-the-output-of-array-using-awk-is-not-in-right-order非常に近い。

要約:awk配列がソートされていません(一般的に言えば)

awkで配列を繰り返すときにfor (i in word)「インデックス」値(下付き文字またはキーとも呼ばれる)が返される順序は次のとおりです。指定されていない渡す基準;伝統的に、これらの配列はハッシュテーブルとして実装され、ハッシュテーブルが特定のハッシュコードモジュールで特定の値になる順序で繰り返され、競合または再ハッシュ(いわゆる「クローズハッシュ」)で修正できます。 。これは、アイテム/キーが挿入される順序とは異なります。これは一般的に決定的ですが、人間の観点からはランダムに見えるほど複雑です。

したがって、あなたの例では、使用するawkと正確なデータに基づいてループが処理される前にアイテムを処理する可能性が高く、結果として一致を含むfor行がに変更され、その後ループが処理しようとしない場合に発生します。一致すれば行ではありません。追加の変更が行われます。同様に、一致しない項目が最初に処理され、一致しない項目が最初に処理されます。異なるawkまたは別のfile1データで実行すると異なるシーケンスが生成される可能性があるため、異なる環境で実行すると異なる結果が生じる可能性があります。LEFTLEFT NAMELEFT NAMELEFTL##T NAMELEFT NAMETYTYTYTYTYTYGGHGAB 8263AB 8263 SCENARIO DEBUG

またFNR==NR(例:file1)ブランチではnew-new substr(old,1,1) substr("##",1,len-1)必要=ありません-。個人的には、対応するサブループを作成する方が自然だと思います。

    old=$i; new=""; for(c=1; c<=length(old); c++) new = new (c%3==1? substr(old,c,1): "#")

違いは小さいが。同じ長さの保護されたバージョンではなく、オプションで後にorが10つ以上の数字で完全に構成されている場合、サブループはfile1のすべての単語を空の文字列に変更し、オプションでドットを知る必要があります。 。+-e

おすすめ記事