質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1726閲覧

文字列をバイト位置でスライスする

SiGat6cFS4zMWqO

総合スコア8

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

3クリップ

投稿2023/01/31 10:08

編集2023/02/06 18:36

実現したいこと

全角と半角が混じった文字列に対して、バイトの位置で指定して文字をスライスしたい。
対象の文字列では、一部のみ抽出しております。
この文字列の場合に、'分'という単語を文字列をスライスする形で抽出したい。

対象の文字列

対象の文字列 data = '0000節分はいつですか1234'

該当のソースコード

python

1data[6:7]

これだと’は’が出力されてしまう。’分’を出力したい。

試したこと

.astype(byte)を試しましたが、エラーとなりました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2023/01/31 10:16

byte列に変換するということでしょうか? bytes(data, encoding='utf-8')[6:7]
TakaiY

2023/01/31 10:25

バイト列として見たときの位置にある、元の文字列(UTF-8とか)の文字を取得したいってことですよね。 すごく面倒そうな気がしますが。 なぜ位置の指定がバイトなのですか?
TakaiY

2023/01/31 10:37

調べてみたら、UTF8だと6バイト目は「分」ではなく「節」でしたので、やっぱりなにをしたいのかよくわからなくなりました。
SiGat6cFS4zMWqO

2023/01/31 11:35

こちらのデータ、もともとのデータ提供元のデータ仕様書がバイト位置で記載されており、その仕様書通り実装したいためです。C言語ですと、全角も2バイトで認識してくれますので、これ以降に文字列があった場合でもバイト位置で文字を取得することができるからです。 bytes(data, encoding='utf-8')[6:7] こちら実行してみますと、出力がバイトとなってしまいました、、、
otn

2023/01/31 12:10

> 全角も2バイトで認識してくれますので ということは、データはUTF-8ではないですね。Shitt_JIS ? euc-jp ? いずれにせよPythonで扱える文字列はUTF-8なので、文字列じゃなくてバイト列として扱うしか無いかと思います。
can110

2023/01/31 12:34

データの文字コードはShift-JIS(cp932)であり 「C言語ですと、全角も2バイトで認識してくれます」という実行ファイルも 「MBCS」ビルドという認識でよいでしょうか。 そのうえでC言語と同様の動きをさせるためには 「分」を抜き出すには「data[6:7]」という1byte分ではなく 「data[6:8]」と2byte分という指定が妥当と思うのですが、いかがでしょうか。
guest

回答2

0

エスパーすると半角文字は1byte、全角文字を2byteとして扱って、そのカウントで部分文字列を取得したいのかなと思うので、以下でどうでしょう?

参考: Pythonでの半角/全角判定方法

python

1import unicodedata 2 3def substr_byte(str2, start, end): 4 l = -1 # index0からにするための調整 5 subStr = "" 6 for w in str2: 7 j = unicodedata.east_asian_width(w) # 全角/半角文字判定 8 if 'F' == j: 9 l += 2 10 elif 'H' == j: 11 l += 1 12 elif 'W' == j: 13 l += 2 14 elif 'Na' == j: 15 l += 1 16 elif 'A' == j: 17 l += 2 18 else: 19 l += 1 20 if l > end: 21 break 22 if l >= start: 23 subStr += w 24 return subStr 25 26print(substr_byte("0000節分はいつですか1234", 6, 7)) 27# 分 28# が表示される

補足

まず、バイト数は文字コードで変わるので、文字コードの指定無いなら確かめた方が良いです。(そもそも依頼主は文字コードよくわかってない or shift jisしか知らない人とは思いますが)
また、その仕様だと data[5:7]とか指定されると何を表示すんだよって感じなので、そこもちゃんと仕様を確認したほうが良いです

投稿2023/02/06 09:27

編集2023/02/06 09:36
takezoux2

総合スコア3

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

私は基本再質問を受け付けない人なので,想像で突っ込み所は全て突っ込む回答をしたいと思います。

最初の指摘はpythonの場合, indexの6から2つ選ぶ時は,6:8としないといけません。
C言語のfor (int i=6; i < 8; ++i)68の部分に相当すると覚えて下さい。

次に,python3の場合,文字列の内部処理はutf-16のコードになっています。
これは半角も全角も1文字2byte相当でインデックスは1文字単位で処理をします。

なので,0000節分はいつですか12346:7は先頭を0とした時の6文字目一つなので「は」となります。

もし,元の仕様書が全角2byte,半角1byteと規定されているなら,
おそらく文字コードはcp932(ShiftJIS)と推定されます。
最近よく使われるutf-8は1文字可変長で基本的に漢字は3byte以上になることが多いので。
全角2byteということでEUC-JPの可能性もあるのですが,半角カナが3byteという地雷を今更
踏みたくはないでしょう。

ということで,独断と偏見でcp932にエンコードして処理をする例を示します。

python

1data = '0000節分はいつですか1234' 2 3print("byte列(cp932):「{}」".format(data.encode('cp932'))) 4print("byte列(cp932)[6:8]:「{}」".format(data.encode('cp932')[6:8])) 5print("文字列[6:8]: 「{}」".format(data.encode('cp932')[6:8].decode('cp932')))
byte列(cp932):「b'0000\x90\xdf\x95\xaa\x82\xcd\x82\xa2\x82\xc2\x82\xc5\x82\xb7\x82\xa91234'」 byte列(cp932)[6:8]:「b'\x95\xaa'」 文字列[6:8]: 「分」

仕様書通りに厳密に実装するにはファイル等から読み込む時には,
byte列で処理しないといけないかもしれませんが,私の関与できる範囲を超えているので好きにして下さい。

投稿2023/01/31 12:35

ujimushi_sradjp

総合スコア2066

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問