一致する行の単語を他の行(最後の2行)と置き換えます。

一致する行の単語を他の行(最後の2行)と置き換えます。

近い質問をたくさん読んだが、問題に対する解決策が見つからなかった。

現在、構造のテキストファイルがあります。

## 誰 <!--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. »

目的は、情報を交換して並べ替えることです。

  • で始まる行から日本語の単語を取り、次の##2行に置き換えます。
  • この行を削除した後、2行
  • この日本語の単語を修正された##行の下に置きます。

このような結果を得るには

## 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

  • 同じ文書を使用してawk2回給紙
  • 最初の実行時:
    • ##見つかったらjw(日本語の単語)とその単語fw(フランス語の単語)を配列として保存し、行番号(NR)でインデックスを付けます。
  • 2番目の実行では、次のことを行います。
    • 行番号があることを確認し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次に、最初の日本語部分を行の2番目のスペースで区切られたフィールドに抽出します(スペースが含まれていないと仮定します)。
  • 次の行を読み、2番目の日本語部分に完全にバッファリングしますj2
  • 次の行をもう一度読み、フランス語の翻訳でバッファリングしますfr
  • 次に、バッファリングされたヘッダーの最初の日本語部分をフランス語翻訳に置き換えて、変更されたヘッダーと2つの日本語部分をそれぞれ1行に印刷します。次に、次の実行行にジャンプします。
  • 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

関連情報