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 가0하나 이상의 숫자로 전체가 구성되어 있으면 하위 루프가 file1의 모든 단어를 빈 문자열로 변경하고 선택적으로 점을 알아야 합니다. .+-e

관련 정보