ファイル全体のすべての行で特定のコンテキストの文字を置き換える方法は?

ファイル全体のすべての行で特定のコンテキストの文字を置き換える方法は?

次の形式の数百の英語の構文を含む大きなファイルがあります。

\phrase
{.   .    .     *     *   }
{I shoul-d've stayed home.}
{aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only replace on this line

\phrase
{ .   .   *  }
{Did you eat?}
{dɪdʒjʊʷˈit? ↗} <- only replace on this line

\phrase
{ *    .  *    .    *  .  .    .     *   .  }
{Yeah, I made some pas-ta if you're hun-gry.}
{ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jər ˈhʌŋ gri.} <- only replace on this line

LaTeX.texファイルです。r各音声記号(音声記号は対応する行の後の\phrase3行ごとに意味)のすべての文字を記号(16進コード)に置き換えたいと思います。ɹU+0279

Emacsで手動で行うのは私にとって面倒です。どういうわけかこの行を見つけて自動的に交換する方法があるかどうか疑問に思います。

例外なくすべてのr文字を置き換える必要がɹありますが、音声記号のみを置き換える必要があり、r英語/非音域テキストはそのまま残ります。

スクリプトなどを使用してこれを実行できますか?私の文書には改行がないので、戦士はいつも\phrase。ありがとうございます!

答え1

awkバージョン(1行に入れることができるメタファイルが必要です)

awk '/\\phrase/ { p=NR ; } 
     NR == p+3 { gsub("r","ɹ")  ; } 
    {print;} ' old-file.tex > new-file.tex

どこ

  • /\\phrase/ { p=NR ; }発生するpすべての行番号に設定されます\phrase
  • NR == p+3 { gsub("r","ɹ") ; } その後、ライン 3 で交換を行います。
  • {print;}すべての行を印刷します。

以下はサンプルを提供します。 (参考ɹeplace

\phrase
{.   .    .     *     *   }
{I shoul-d've stayed home.}
{aɪ ʃʊd‿əv ˈsteɪd ˈhoʊm.} <- only ɹeplace on this line

\phrase
{ .   .   *  }
{Did you eat?}
{dɪdʒjʊʷˈit? ↗} <- only ɹeplace on this line

\phrase
{ *    .  *    .    *  .  .    .     *   .  }
{Yeah, I made some pas-ta if you're hun-gry.}
{ˈjɛə, aɪ ˈmeɪd səm ˈpɑ stəʷɪf jəɹ ˈhʌŋ gɹi.} <- only ɹeplace on this line

答え2

awk 'c&&!--c {gsub(/r/,"ɹ")} /\\phrase/ {c=3} 1' file > newfile

c&&!--cawkロジックを実装する一般的な慣用語ですwhile getline引用する

この条件以降の動作は、1から0に減少した場合にのみ実行されます。

リテラルを一致させると、一致後に3行目でのみ実行されるように'\phrase'設定され、c=3すべての一致に対して繰り返されます。gsub()

答え3

Emacsを使用しているので...

悪の道/ビーム

すでにevil-modeVimをインストールしている場合、またはVimに切り替えている場合は、次のことができます。

:g/^\\phrase/+3s/r/ɹ/g

これが最も簡単です。

キーボードマクロモード

既存のEmacsを引き続き使用しながら、キーボードマクロを使用できます。C-x ( C-M-s ^\\phrase Enter C-n C-n C-n C-a C-space C-e C-M-% r Enter ɹ Enter ! C-x ) C-u 2 C-x e

C-x (マクロ開始、C-x )マクロ終了、C-x eマクロ実行C-u 2/マクロを2回実行するようにC-2変更します。計算を望まない場合は、大きな数字を使用することもできます。正規表現を検索してみてください。 3行下に移動してその行を選択し、置換を選択します。何を交換するかを尋ねるメッセージが表示されたら、選択肢のすべての交換を受け入れることを意味します。C-x eC-u 10000C-M-sC-M-%!

エリプスロード

*scratch*バッファを開いて実行することもできます(C-M-xコードの上にカーソルを置きます)。

(with-current-buffer "foo"
  (goto-char (point-min))
  (while (re-search-forward "^\\\\phrase" nil t)
    (forward-line 3)
    (replace-string-in-region "r" "ɹ" (point) (line-end-position))))

fooこれを実行したいバッファの名前はどこにありますか?

編集:replace-string-in-regionEmacs 28.1(作成時の最新バージョン)に導入されました。以前のEmacsを使用している場合は、代わりに次のものを使用できsearch-forwardますreplace-match

(with-current-buffer "foo"
  (goto-char (point-min))
  (while (re-search-forward "^\\\\phrase" nil t)
    (forward-line 3)
    (while (search-forward "r" (line-end-position) t)
      (replace-match "ɹ"))))

シェルコマンドのフィルタリング方法

ここにある他の答えの1つのように、外部コマンドを使用してEmacsバッファをフィルタリングすることもできます。C-x h C-u M-| <command> Enter

C-x hバッファ全体を選択します。M-|選択項目をフィルタリングするコマンドを入力するように求められます。選択内容が一時バッファに保存されるのではなく、出力に置き換えられるように修正されC-uました。M-|

答え4

標準sed:

sed '/^\\phrase$/{n;n;n;s/r/ɹ/g;}'

y/r/ɹ/オーバーライドは、文字がユーザーロケールで文字として扱われる限り、s/r/ɹ/gPOSIX準拠の実装でも機能しますが、マルチバイト文字をサポートしない実装(UTF-8の場合)でも機能するため、移植性に優れています。 ;シングルバイトでエンコードされている文字エンコーディングが見つかりません。sedɹs/r/ɹ/gsedɹɹ

ɹユーザーのロケールで正しくエンコードするには、zsh次の手順を実行します。

sed $'/^\\\\phrase$/{n;n;n;s/r/\u0279/g;}'

ユーザーのロケールで\u0279その文字のエンコードに拡張されます。ɹ


¹今、$'\uXXXX'他のシェルはこれをサポートしていますが、一部のシェルではコマンドが実行されるsedロケールです。 ksh93では、ユーザーのロケールに関係なく常にUTF-8に拡張されます。ロケールの文字セットでその文字が使用できない場合でも、他のシェルは動作が異なります。エラーが発生しますzsh

関連情報