[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[debian-users:58109] Re: バックスラッシュと円の問題



松井です。
皆さま レスありがとうございます。

今日現れたエディタでの不可解な挙動について書きとめておきますが、
同じものをペーストして
バックスラッシュに続く行では半角円になり
別の行では全角円になってしまう。
また、バックスラッシュをコピペしても半角円にしかならないこともあります。

バックスラッシュが表示される方のdebianでは
$ ls /usr/share/fonts/
cmap  truetype  type1  X11
こっちだけに opentype がないですね。
やはり tex のインストール時に opentype, ipag.ttf そのあたりがインストールされたのかもです。

まず綾小路さんの方法での実行結果について書いていきます。
以下は全て円が表示される方のdebianでの実行結果です。

$ ttx -d . /usr/share/fonts/opentype/ipafont-gothic/ipag.ttf
Dumping "/usr/share/fonts/opentype/ipafont-gothic/ipag.ttf" to "./ipag.ttx"...
Dumping 'GlyphOrder' table...
Dumping 'head' table...
Dumping 'hhea' table...
Dumping 'maxp' table...
Dumping 'OS/2' table...
Dumping 'hmtx' table...
Dumping 'cmap' table...
Dumping 'fpgm' table...
Dumping 'prep' table...
Dumping 'cvt ' table...
Dumping 'loca' table...
Dumping 'glyf' table...
Dumping 'name' table...
Dumping 'post' table...
Dumping 'gasp' table...
Dumping 'GDEF' table...
Dumping 'GSUB' table...
Dumping 'vhea' table...
Dumping 'vmtx' table...

ここは何かの設定を行ったということでよろしいでしょうか。

$ grep '<map code="0x\(5c\|a5\)"' ipag.ttx
$ grep '"\(aj291\|aj711\)"' ipag.ttx
の結果は
綾小路さんがメールに書かれている結果と全く同一でした。

フォント設定については、
gedit:
システムの固定幅フォント (Droid Sans Fallbac) を使う
pluma:
システムの固定幅フォント (Monospace 10) を使う
ターミナルのフォント設定はどこから見れるのか分かりません。

$ hexdump -C backslash_ascii_5c.txt
00000000  5c 0a                                             |\.|
00000002
$ cat backslash_ascii_5c.txt
\
$ hexdump -C yen_latin1_a5.txt
00000000  a5 0a                                             |..|
00000002
$ cat yen_latin1_a5.txt
�
このようにターミナルでは文字化けしていますが、geditでshiftJISにより開くと
・
なっています。
$ hexdump -C yen_utf8_c2a5.txt
00000000  c2 a5 0a                                          |...|
00000003
$ cat yen_utf8_c2a5.txt
¥

$ printf '0000000: 5c' | xxd -g 1 -revert - backslash_ascii_5c.txt
$ printf '0000000: a5' | xxd -g 1 -revert - yen_latin1_a5.txt
$ printf '0000000: c2 a5' | xxd -g 1 -revert - yen_utf8_c2a5.txt
この三つのコマンドはなぜか何の結果も返ってきません。

長南さんの sed による方法では
$ cat TeX25.tex | sed 's/¥/\\/' > TeX25_after.tex
$ cat TeX25.tex | sed sed 'y/¥/\\/' > TeX25_after.tex
$ cat TeX25.tex | sed 's/\xC2\xA5/\\/' > TeX25_after.tex
$ cat TeX25.tex | sed 'y/\xC2\xA5/\\/' > TeX25_after.tex
od で確かめて a5 も c2 もなくなってしまっても、やはり正常にコンパイルされません。

最後に野池さんの方法です。
TeX25.tex から
nkf の -wd と -w でそれぞれ
TeX25-wd.tex と TeX25-w.tex を作り、

$ file TeX25.tex
TeX25.tex: LaTeX 2e document, Non-ISO extended-ASCII text, with CRLF line terminators
$ nkf --guess TeX25.tex
Shift_JIS (CRLF)
$ file TeX25-wd.tex
TeX25-wd.tex: LaTeX 2e document, UTF-8 Unicode text
$ nkf --guess TeX25-wd.tex
UTF-8 (LF)
$ file TeX25-w.tex
TeX25-w.tex: LaTeX 2e document, UTF-8 Unicode text, with CRLF line terminators
$ nkf --guess TeX25-w.tex
UTF-8 (CRLF)

TeX25-wd.tex と TeX25-w.tex はどちらも正常にコンパイルできました。
この結果からすると、文字コードの問題だったということでよろしいのでしょうか。

---
Kenji Matsui


On 08/19/2016 05:49 AM, AYANOKOUZI, Ryuunosuke wrote:
松井さま

綾小路です。

At Thu, 18 Aug 2016 18:28:18 +0900,
Kenji Matsui <kmatsui@xxxxxxxxxxxxxxxxxx> wrote:

まずフォントの状況ですが、
バックスラッシュが出力されるdebianでは
$ fc-match monospace
DroidSansFallbackFull.ttf: "Droid Sans Fallback" "Regular"
$ fc-match :lang=ja
DroidSansFallbackFull.ttf: "Droid Sans Fallback" "Regular"
円が出力されるdebianでは
$ fc-match monospace
ipag.ttf: "IPAゴシック" "Regular"
$ fc-match :lang=ja
ipag.ttf: "IPAゴシック" "Regular"
となっておりました。
$ gsettings set org.gnome.desktop.interface font-name 'Droid Sans Fallback'
$ fc-cache
の後に再ログインして円が出力される方をバックスラッシュが出力される方に合わせようとおもったのですけど、うまくいきませんでした。
フォントの変更方法はよく分かりません。

ipag.ttf に含まれる U+005c と U+00a5 に対応するグリフは異なる [1] ので、
バイト列を utf8 エンコーディングとして解釈して ipag.ttf を使って表示すれば、
バックスラッシュと円記号は違った文字として表示されるはずです。

今問題になっているアプリケーション (ターミナル、gedit、pluma)
のフォント設定が ipag.ttf を参照するようになっているか否かを
再確認してみるのはいかがでしょうか。

また、0x5c、0xa5、0xc2a5 というバイト列を含むファイルを作って [2]、
それらが期待通り表示されるか確認してみるのも良いかもしれません。
アプリケーションが適切にエンコーディングを判別して、ipag.ttf を使って表示したなら、
それぞれバックスラッシュ、円記号、円記号のように表示されるはずです。

[1]
$ ttx -d . /usr/share/fonts/opentype/ipafont-gothic/ipag.ttf
$ grep '<map code="0x\(5c\|a5\)"' ipag.ttx
      <map code="0x5c" name="aj291"/><!-- REVERSE SOLIDUS -->
      <map code="0xa5" name="aj711"/><!-- YEN SIGN -->
      <map code="0x5c" name="aj291"/><!-- REVERSE SOLIDUS -->
      <map code="0xa5" name="aj711"/><!-- YEN SIGN -->
      <map code="0x5c" name="aj291"/><!-- REVERSE SOLIDUS -->
      <map code="0xa5" name="aj711"/><!-- YEN SIGN -->
$ grep '"\(aj291\|aj711\)"' ipag.ttx
    <GlyphID id="258" name="aj291"/>
    <GlyphID id="466" name="aj711"/>
    <mtx name="aj291" width="1024" lsb="51"/>
    <mtx name="aj711" width="2048" lsb="404"/>
      <map code="0x5c" name="aj291"/><!-- REVERSE SOLIDUS -->
      <map code="0xa5" name="aj711"/><!-- YEN SIGN -->
      <map code="0xffe5" name="aj711"/><!-- FULLWIDTH YEN SIGN -->
      <map code="0x5c" name="aj291"/><!-- REVERSE SOLIDUS -->
      <map code="0xa5" name="aj711"/><!-- YEN SIGN -->
      <map code="0xffe5" name="aj711"/><!-- FULLWIDTH YEN SIGN -->
      <map code="0x5c" name="aj291"/><!-- REVERSE SOLIDUS -->
      <map code="0xa5" name="aj711"/><!-- YEN SIGN -->
      <map code="0xffe5" name="aj711"/><!-- FULLWIDTH YEN SIGN -->
    <TTGlyph name="aj291" xMin="51" yMin="104" xMax="972" yMax="1538">
    <TTGlyph name="aj711" xMin="404" yMin="104" xMax="1645" yMax="1538">
      <psName name="aj291"/>
      <psName name="aj711"/>
      <ClassDef glyph="aj291" class="1"/>
      <ClassDef glyph="aj711" class="1"/>
    <mtx name="aj291" height="2048" tsb="264"/>
    <mtx name="aj711" height="2048" tsb="264"/>

[2]
$ printf '0000000: 5c' | xxd -g 1 -revert - backslash_ascii_5c.txt
$ printf '0000000: a5' | xxd -g 1 -revert - yen_latin1_a5.txt
$ printf '0000000: c2 a5' | xxd -g 1 -revert - yen_utf8_c2a5.txt

バイナリーデータとして ¥ を \ に置き換えれば一番いいのかなと思いまして、
$ cat tf9.txt
\,¥, a
普通のテキストを16進数テキストに変換
$ hexdump tf9.txt
0000000 2c5c a5c2 202c 0a61
0000008
(エディタにコピペすると、0000000 と 0000008 のサイズが違ってきます)
$ hexdump tf9.txt > tf9.hex
16進数テキストをバイナリファイルに変換
$ xxd -r -p tf9.hex tf9.bin
円のa5(8進数で245)をバックスラッシュの5c(8進数で134)に置き換える
$ tr '¥245' '¥134' < tf9.bin > tf9_after.bin
c2(8進数で302)を削除する
$ tr -d '¥302' < tf9_after.bin > tf9_after_2.bin
最後のバイナリファイルを16進数テキストに変換
$ xxd -p tf9_after_2.bin tf9_after_2.hex
と、ここまでやっても
$ cat tf9_after_2.hex
00000002c5ca5c2202c0a610000008
というように全く変更されていません。

ちなみに、hexdump で -C オプションをつけると並び方が変わってきます。
$ hexdump -C tf9.txt
00000000  5c 2c c2 a5 2c 20 61 0a                           |¥,.., a.|
00000008
$ hexdump -C tf9.txt > tf9_2.hex
$ xxd -r -p tf9_2.hex tf9_2.bin
$ diff -s tf9.bin tf9_2.bin
バイナリーファイル tf9.bin とtf9_2.bin は異なります

マニュアルを見てもよく分からなかったのですけど
-C オプションを付けた場合が特殊であれば
-C オプションをつけないやり方で押し通せばよいのかもしれません。

0xa5 を 0x5c に変換する方針はしばしば問題を引き起こします。
なぜなら、円記号に対応するバイト列表現はエンコーディングに依存する [3] からです。
また、この方針はバイト単位で変換を行うので、文字という意味単位は失われ、
意図しない変換が行われる場合があります [4]。
入力エンコーディングが utf8 ならば、文字単位の変換は簡単です [5]。
しかしながら、「古いファイル」が Shift_JIS エンコーディングの場合、
[5] で挙げた concept code は使えません。

[3]
| ascii | latin1 | utf8 =================+=======+========+==============
バックスラッシュ | 0x5c  | 0x5c   | 0x5c
円記号           |       | 0xa5   | 0x2ca5
-----------------+-------+--------+--------------

[4]
$ printf '\¥づ' | xxd -g 1
0000000: 5c c2 a5 e3 81 a5                                \.....
$ printf '\¥づ' | tr '\245' '\134' | xxd -g 1
0000000: 5c c2 5c e3 81 5c                                \.\..\

[5]
$ printf '\¥づ' | perl -C -0777 -ne 'while (m/(.)/g) { if($1 eq "\N{U+00a5}") { print "\N{U+005c}"; } else { print $1; } }' | xxd -g 1
0000000: 5c 5c e3 81 a5                                   \\...

綾小路龍之介



On 08/19/2016 01:15 PM, 長南洋一 wrote:
長南です。

綾小路さんのメールより [debian-users:58105]

0xa5 を 0x5c に変換する方針はしばしば問題を引き起こします。

また、この方針はバイト単位で変換を行うので、文字という意味単位は失われ、
意図しない変換が行われる場合があります [4]。

エンコーディングが UTF-8 だったら、tr の代わりに sed が使えませんか。
これですめば、perl を使うより楽なんですけれど。

$ printf '\¥づ' |od -t x1
0000000 5c c2 a5 e3 81 a5
$ printf '\¥づ' |sed 's/¥/\\/' |od -t x1
0000000 5c 5c e3 81 a5
$ printf '\¥づ' |sed 'y/¥/\\/' |od -t x1
0000000 5c 5c e3 81 a5
$ printf '\¥づ' |sed 's/\xC2\xA5/\\/' |od -t x1
0000000 5c 5c e3 81 a5
printf '\¥づ' |sed 'y/\xC2\xA5/\\/' |od -t x1
0000000 5c 5c e3 81 a5



On 08/19/2016 02:05 PM, Kenzi NOIKE wrote:
野池です.

また、普通のエディタ上では
\¥
と区別されて表示されるのが、バイナリーデータとしては
$ hexdump tf1.txt
0000000 5c5c 000a
0000003
というように同じになっているのは訳がわかりません。
$ cat tf1.txt
¥¥
これをエディタにコピペすると ¥¥ になってしまいます。
geditにしろplumaにしろ
エディタで入力しようとする時に、バックスラッシュキーを押すと最初は
¥
が表示されていて、続けて何かのアルファベットキー(ここではf)を押すと
\f
というように自動で表示が切り替わります。
エディタにおいて同じキーを押すことにより、ある時は \ が出力され、一旦ターミナルを操作して後に同じキーを押すと ¥ が出力されたり、
というような挙動を示すのも私にはかなり不可解でした。

この部分を信じると,
現象の根源は,「バックスラッシュ」と「円記号」とは違うところにあるのではないでしょうか.
¥, f とキー入力したときに,表示が ¥ → \f と変化するのは,
エディタの機能による見た目だけの変化なのではないかと想像しています.


目的は,

昔のファイルを処理しなければいけないことがありまして、
\ であるべき所が
¥ になっており
そのままでは tex のコンパイルが正常に行えないため
いつも手作業で書き換えています。
何とかこの ¥ を全て一気に書き換えられないかなと思っておりました。

だそうですが,これは,実のところは,

「
「昔のファイル」が SJIS-DOS でエンコードされているので,
tex(latex)のコンパイルが通らなかった.

手作業で書き換えたときに,たまたま UTF8-unix エンコードで保存されたために,
tex(latex) のコンパイルが通るようになった.
」

だったのではないでしょうか.
もし,そうだったとすると,するべきことは「バックスラッシュ」と「円記号」の書き換えではなく,
SJIS → UTF8 変換ですので,たとえば nkf を使うのであれば,

$ nkf -wd 昔のファイル > 今のファイル
($ nkf -w 昔のファイル > 今のファイル
かも).

になります.