일치하는 줄의 단어를 다른 줄(마지막 두 줄)과 바꿉니다.

일치하는 줄의 단어를 다른 줄(마지막 두 줄)과 바꿉니다.

가까운 질문을 많이 읽었지만 문제에 대한 해결책을 찾지 못했습니다.

현재 구조의 텍스트 파일이 있습니다.

## 誰 <!--QR2Y;1;2023-04-18-->
だれ
quelqu'un, qui, quel 

田中さんてだれですか。
« Qui est ce M. Tanaka ? » 

## 歌う <!--T2B7;1;2023-04-18-->
うたう
chanter, réciter

ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »

목적은 정보를 교환하고 재정렬하는 것입니다.

  • 로 시작하는 줄에서 일본어 단어를 가져와 ##다음 두 줄로 바꿉니다.
  • 이 줄을 삭제한 후 두 줄
  • 이 일본어 단어를 수정된 ##줄 아래에 넣으세요.

이런 결과를 얻으려면

## quelqu'un, qui, quel  <!--QR2Y;1;2023-04-18-->
だれ

田中さんてだれですか。
« Qui est ce M. Tanaka ? » 

## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう

ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »

구조는 항상 똑같습니다. 가변부분은 <!--X0X0;0;000-00-00-->항상 변하는 부분이고 때로는 전혀 존재하지 않는 부분이다.

이것은 sed해결책인 것 같지만 문서에서 약간 길을 잃었습니다...

답변1

솔루션awk

  • 동일한 문서를 사용하여 awk두 번 급지
  • 첫 번째 실행 시:
    • ##발견 되면 jw(일본어 단어)와 해당 단어 fw(프랑스어 단어)를 배열로 저장하고, 행 번호( NR)로 색인을 지정합니다.
  • 두 번째 실행에서는 다음을 수행합니다.
    • 줄 번호가 있는지 확인한 fw후 일본어 단어를 프랑스어 단어로 바꾸고 해당 일본어 단어를 인쇄합니다.
    • 방금 배치한 프랑스어 단어가 있는 줄을 제외한 모든 줄을 인쇄합니다.
awk '
  NR == FNR && /^##/ { jw[NR]=$2; nr=NR; }
  NR == nr+2 {fw[NR-2]=$0}
  NR>FNR {
    if(FNR in fw) { $2 = fw[FNR]; print; print jw[FNR]; }
    else { if (!(FNR-2 in fw)) print; }}
' file file

산출:

## quelqu'un, qui, quel  <!--QR2Y;1;2023-04-18-->
だれ

田中さんてだれですか。
« Qui est ce M. Tanaka ? » 

## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう

ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »

답변2

원패스 솔루션은 다음과 같습니다.

awk '/^##/ {hdr=$0; j1=$2; getline; j2=$0; getline; fr=$0;
           sub(/## [^<]+/, "## " fr " ", hdr); print hdr; print j1; print j2; next } 1' input
  • 그러면 시작 패턴으로 헤더 행이 식별되어 ##변수에 저장됩니다 hdr.
  • j1그런 다음 첫 번째 일본어 부분을 줄의 두 번째 공백으로 구분된 필드로 추출합니다 (공백이 포함되어 있지 않다고 가정합니다).
  • 다음 줄을 읽고 두 번째 일본어 부분에 완전히 버퍼링합니다 j2.
  • 다음 줄을 다시 읽고 프랑스어 번역으로 버퍼링합니다 fr.
  • 그런 다음 버퍼링된 헤더의 첫 번째 일본어 부분을 프랑스어 번역으로 대체하여 수정된 헤더와 두 개의 일본어 부분을 각각 한 줄에 인쇄합니다. 그런 다음 다음 실행 줄로 점프합니다.
  • 1다른 모든 줄은 규칙 블록 외부에 있기 때문에 수정 없이 인쇄됩니다(외견상 길을 잃은 것처럼 보임).

답변3

1패스로 멀티바이트 문자를 지원하는 awk를 사용하세요(일본어 단어의 경우).

awk '
    BEGIN { RS=""; ORS="\n\n"; FS=OFS="\n" }
    /^##/ { split($1,a," "); $1=a[1] " " $3 " " a[3]; $3=$2; $2=a[2] }
1' file
## quelqu'un, qui, quel  <!--QR2Y;1;2023-04-18-->
だれ

田中さんてだれですか。
« Qui est ce M. Tanaka ? »

## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう

ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »

레코드 사이에 빈 줄이 없어 RS=""작동하지 않으면 다음과 같이 할 수 있습니다(여전히 1패스, ##각 청크에 대해 3줄 버퍼링).

$ cat tst.awk
BEGIN { FS=OFS="\n" }
/^##/  { lineNr=1; buf = $0; next }
lineNr { lineNr++; buf = buf RS $0 }
lineNr == 3 {
    $0 = buf
    split($1,a," "); $1=a[1] " " $3 " " a[3]; $3=$2; $2=a[2]
    lineNr = 0
}
!lineNr

$ awk -f tst.awk file
## quelqu'un, qui, quel  <!--QR2Y;1;2023-04-18-->
だれ

田中さんてだれですか。
« Qui est ce M. Tanaka ? »

## chanter, réciter <!--T2B7;1;2023-04-18-->
歌う
うたう

ピアノに合わせて歌う。
« Chanter accompagné d'un piano. »

답변4

그리고 perl:

perl -00pe 's/^(##\s*)(.*?)(\s*<!--.*-->\n)(.*)\n(.*)/$1$5$3$2\n$4/' your-file

관련 정보