次の形式の数百の英語の構文を含む大きなファイルがあります。
\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
各音声記号(音声記号は対応する行の後の\phrase
3行ごとに意味)のすべての文字を記号(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&&!--c
awk
ロジックを実装する一般的な慣用語ですwhile
getline
。引用する。
この条件以降の動作は、1から0に減少した場合にのみ実行されます。
リテラルを一致させると、一致後に3行目でのみ実行されるように'\phrase'
設定され、c=3
すべての一致に対して繰り返されます。gsub()
答え3
Emacsを使用しているので...
悪の道/ビーム
すでにevil-mode
Vimをインストールしている場合、または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 e
C-u 10000
C-M-s
C-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-region
Emacs 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/ɹ/g
POSIX準拠の実装でも機能しますが、マルチバイト文字をサポートしない実装(UTF-8の場合)でも機能するため、移植性に優れています。 ;シングルバイトでエンコードされている文字エンコーディングが見つかりません。sed
ɹ
s/r/ɹ/g
sed
ɹ
ɹ
ɹ
ユーザーのロケールで正しくエンコードするには、zsh
次の手順を実行します。
sed $'/^\\\\phrase$/{n;n;n;s/r/\u0279/g;}'
ユーザーのロケールで\u0279
その文字のエンコードに拡張されます。ɹ
¹今、$'\uXXXX'
他のシェルはこれをサポートしていますが、一部のシェルではコマンドが実行されるsed
ロケールです。 ksh93では、ユーザーのロケールに関係なく常にUTF-8に拡張されます。ロケールの文字セットでその文字が使用できない場合でも、他のシェルは動作が異なります。エラーが発生しますzsh