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

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

新規登録して質問してみよう
ただいま回答率
85.48%
タブ

コンテンツの上下左右に参照用のメニューを設けることで、複数の要素やページの表示を可能にするユーザーインターフェイスパターンのこと。メニューをクリックすると、一つの要素が可視化され、他の要素は見えなくなる。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

置換

置換とは文字列中の特定の文字に対して、別の文字列に置き換えることを指します。

Q&A

解決済

1回答

2739閲覧

javascriptでsplitを使ってタブで分割すると、""で囲まれた内部のタブまで分割されてしまいます。""で囲まれたタブで区切られないようにするにはどうしたらよろしいでしょうか?

terumae

総合スコア2

タブ

コンテンツの上下左右に参照用のメニューを設けることで、複数の要素やページの表示を可能にするユーザーインターフェイスパターンのこと。メニューをクリックすると、一つの要素が可視化され、他の要素は見えなくなる。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

置換

置換とは文字列中の特定の文字に対して、別の文字列に置き換えることを指します。

0グッド

0クリップ

投稿2020/06/11 03:07

編集2020/06/11 08:02

前提・実現したいこと

前提

https://teratail.com/questions/269193
で解決したと思った件に関してですが
自分の確認不手際で見逃している箇所がありました。
申し訳ございません。

また,javascriptを触り始めて3日目程度の知識が無いので
実現したいことや質問に不慣れな部分がある事に関しても
お手数お掛け致します。

実現したいこと

Javascriptで頂いたTSVファイル読み込んでいるのですが
タブ区切りを行った際にデータ部分にタブが混じっているものがあり
本来区切る必要が無い箇所でタブ区切りがされてしまいます
※頂くTSVを相手側でデータ内のタブを考慮して修正して頂く事が出来ないので
こちら側で対応しなければならない形です。

なので、タブ区切りを行う前にreplaceを使い
データ部分のタブを空白に置き換えることで
不必要な分割がされないようにしようとしております。

もしくは、タブ区切りを行う際に先頭が
ダブルクオーテーションの箇所は
タブ区切りを行わないなどは可能でしょうか?

発生している問題・エラーメッセージ

下記TSVのデータがあるのですが

(異常:データ部分にTAB有り)
[TAB]6000[TAB]"販売者[TAB](株)佐々木 "[TAB][TAB]"内容量[TAB] 200g
原材料名 [TAB]ブドウ糖、香料
賞味期限 [TAB]製造日より6ヶ月以内
保存方法 [TAB]直射日光を避け常温
配送方法 [TAB]宅配便(常温)
提供事業所 [TAB] (株)佐々木"[TAB]1か月間

(異常:データ部分も区切られてしまう)
6000,"販売者,(株)佐々木",,
内容量, 200g
原材料名 ,ブドウ糖、香料
賞味期限 ,製造日より6ヶ月以内
保存方法 ,直射日光を避け常温
配送方法 ,宅配便(常温)
提供事業所 ,株)佐々木",
1か月間

本来""で囲まれた部分のタブの箇所で
分割がされたくない部分が分割されてしまいます

本来であれば
"販売者[TAB](株)佐々木 "の中の[TAB]と

"内容量[TAB] 200g
原材料名 [TAB]ブドウ糖、香料
賞味期限 [TAB]製造日より6ヶ月以内
保存方法 [TAB]直射日光を避け常温
配送方法 [TAB]宅配便(常温)
提供事業所 [TAB] (株)佐々木"
の中の[TAB]で区切られたくない形です。

""の無いのTABを空白に置き換えるか
もしくは、[TAB]区切りの際に先頭がダブルクオーテーションだったら
区切らない方法など無いでしょうか?

目指すべきは""内に[TAB]が入っていてもいいので
下記のように綺麗に分割出来ればいい形です。

6000,"販売者[TAB](株)佐々木 ",,"内容量[TAB] 200g
原材料名 [TAB]ブドウ糖、香料
賞味期限 [TAB]製造日より6ヶ月以内
保存方法 [TAB]直射日光を避け常温
配送方法 [TAB]宅配便(常温)
提供事業所 [TAB] (株)佐々木",1か月間

もしくは、

6000,
"販売者(株)佐々木 ",,"内容量 200g
原材料名 ブドウ糖、香料
賞味期限 製造日より6ヶ月以内
保存方法 直射日光を避け常温
配送方法 宅配便(常温)
提供事業所 (株)佐々木",
1か月間

該当のソースコード

javascript
https://teratail.com/questions/269193の置換方法の正規表現を入れてみました。

function getArraysFromTSV(tsvFile): Promise<string[][]> {
return new Promise(resolve => {
let appReader = new FileReader();
appReader.onload = function (e) {
const rawString = ${e.target.result};

resolve( **rawString.replace(/(["].+?)\t(.+?["])/g**,"$1$2") .split('\n') .map(string => string.split("\t")) .map( row => row.map( cell => cell.charAt(0) === '"' && cell.charAt(cell.length - 1) === '"' ? cell.substring(1, cell.length - 1).replace(/<!--NEWLINE-->/g, "\n").replace(/""/g, '"') : cell ) ).filter(row => row.join('').trim() !== "") ) }; appReader.readAsText(tsvFile);

});
}

### 試したこと 正規表現の箇所を変更して console.log(rawString.replace(/(["].+?)\t(.+?["])/g,"$1$2")) を書いてみてgoogle chromeの検証のconsoleを確認してみた形です。

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

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

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

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

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

m.ts10806

2020/06/11 03:15

いきなり出てきた「test」は何者ですか?
terumae

2020/06/11 03:18

y_waiwaiさん そちらで解決済みになったと思ったのですが "販売者[TAB](株)佐々木 "の[TAB]は消えたのですが 下記の箇所の[TAB]が消えていなかったことに気づき再度 詳細なテストデータを記載して投げさせてもらった形になります。 "内容量[TAB] 【宮崎} 原材料名 [TAB]ブドウ糖、香料 賞味期限 [TAB]製造日より6ヶ月以内 保存方法 [TAB]直射日光を避け常温 配送方法 [TAB]宅配便(常温) 提供事業所 [TAB] (株)池商"
y_waiwai

2020/06/11 03:26

ならそこらへん説明しましょうよ。 以前の回答ガン無視してどーするんですか
terumae

2020/06/11 04:20 編集

y_waiwai さん 大変すみません。 前の質問に対して再確認した際に気づいた点を編集して記載するべきでした。 teratailの運用と言いますか使い方をまだちゃんと把握できていなく申し訳ないです。 回答頂いたMashiroさんにも申し訳ないことを致しました。 y_waiwaiさん m.ts10806さん 質問内容もう少し精査して前の投稿に編集する形にして こちらの質問は削除したいと思います ※質問の削除仕方がすぐに分からずこちらの内容を編集した形になります。 申し訳ございませんでした。
Lhankor_Mhy

2020/06/11 03:54

ご提示のコードを試してみましたが、かっこの対応があっておらず、文法エラーが出ます。 また、不要のかっこを当方で削除して試してみましたが、ご提示のような 6000,"販売者,(株)佐々木",, 内容量, 200g 原材料名 ,ブドウ糖、香料 賞味期限 ,製造日より6ヶ月以内 保存方法 ,直射日光を避け常温 配送方法 ,宅配便(常温) 提供事業所 ,株)池商", 1か月間 という結果にはなりませんでした。 (そもそも、splitはどこでしょう?) 問題が再現するコードをご提示ください。
terumae

2020/06/11 03:59

Lhankor_Mhyさん  確認して頂きありがとうございます。 質問内容が色々足りていないので伝わるように精査しようと思います。
Lhankor_Mhy

2020/06/11 04:50

あと、標準的なTSVですと、文字列に"が含まれる場合に""とエスケープされるはずですが、それはご考慮されていますか? 個人的な意見を申し上げるなら、車輪の再発明をせずにライブラリなどを利用した方がいいのではないかと思いますよ。 https://www.papaparse.com/
terumae

2020/06/11 07:36

Lhankor_Mhyさん コメントありがとうございます。 エスケープに関しては貰ったTSVを見る限り考慮はされていないと思われます。 ライブラリの確認をしてみます。 ありがとうございます。 ライブラリ確認してみます!
guest

回答1

0

ベストアンサー

コメント欄で提案されているように、ライブラリを探すのが早いと思います。

splitを使ってタブで分割

データフィールドの中に、区切り文字と同じ文字を含められるテキストフォーマット(CSV,TSV)では、split()で単純に分割するのではなく、while ループなどを使い1文字ずつ総当りしてください。

TSVですと、着目すべきは、", \t でしょうか。(複数行なら \n も含む)

また、正規表現にこだわっていらっしゃるようですが、不慣れであれば簡単な用法に留めます。

  1. 改行コード統一
  2. String.replace() (総当り用途)のマッチ条件

以下、1行のデータ解析について例示します。

javascript

1let tsv =`\t6000\t"販売者\t(株)佐々木 "\t\t"内容量\t 200g 2原材料名 \tブドウ糖、香料 3賞味期限 \t製造日より6ヶ月以内 4保存方法 \t直射日光を避け常温 5配送方法 \t宅配便(常温) 6提供事業所 \t (株)池商"\t1か月間`; 7let pointer = 0; 8let inQuote = false; 9let rslt = []; 10 11tsv = tsv.replace(/\r?\n/g, "\n"); // 1. 12tsv.replace(/["\t\n]/g, ($0,offset) => { // 2. 13 switch( $0 ) { 14 case "\t": 15 if( inQuote ) break; 16 console.log( `[TAB] ${offset} ${tsv.substring(pointer, offset)}` ); 17 rslt.push( tsv.substring(pointer, offset) ); 18 pointer = offset+1; 19 break; 20 case "\n": 21 console.log(`[LF] ${offset}`); 22 break; 23 case '"': 24 //if( offset && tsv.charAt(offset-1)==="\" ) break; 25 if( offset && tsv.charAt(offset-1)==="\" ) break; 26 console.log(`[q] ${offset}`); 27 if( inQuote ) { 28 console.log( `[Q] ${offset} ${tsv.substring(pointer, offset)}` ); 29 rslt.push( tsv.substring(pointer, offset) ); 30 } 31 inQuote = !inQuote; 32 pointer = offset + 1; 33 34 break; 35 } 36}); 37if( pointer < tsv.length ) { 38 rslt.push( tsv.substring(pointer) ); 39} 40rslt.filter( s => s.length ); 41// ["6000", "販売者 (株)佐々木 ", "内容量 200g↵原材料名 ブドウ糖、香料↵賞味期限 製造日より6ヶ月以内↵保存方法 直射日光を避け常温↵配送方法 宅配便(常温)↵提供事業所 (株)池商", "1か月間"]

テストは不十分ですので、console.log() を残してあります。

投稿2020/06/11 05:07

編集2020/06/12 21:04
AkitoshiManabe

総合スコア5432

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

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

terumae

2020/06/11 07:38

AkitoshiManabeさん 回答ありがとうございます。 Lhankor_Mhyさんのコメントにもあるように ライブラリ確認してみます! その上での上記の参考に試してみようと思います。
terumae

2020/06/12 11:40

AkitoshiManabeさんの参考に とても不出来な形ですが実現したいことを下記のコードで やってみました。 while ループなどを使い1文字ずつ総当りがとてもヒントになり助かりました ありがとうございます。 // 対象文字列 let rawString = `6000 "販売者 (株)佐々木 " "内容量 200g" 1 100`          (6000\t"販売者\t(株)佐々木 "\t\t"内容量\t200g"\t1\t100) //全体タブ区切り let arrString = rawString.split("\t") //配列の数を数える let count = arrString.length let doubleString = [] //配列の要素の数だけループ処理を行いダブルクオーテーションがある配列のデータを確認 //ダブルクォーテーションで始まる配列のデータに終了のダブルクオーテーションがあるか確認する //条件 開始と終了があるのであれば2個なので偶数で完結したデータ // 開始しか無い場合1個なので奇数で未完のデータ //偶数はそのまま新しい配列に格納 //奇数は次の配列のデータの結合させて偶数になるか確認 //ならなければ再度結合を繰り返して偶数になったら新しい配列に格納 //出来た配列を出力させて処理は完了 for(i=0; i<count;i++){ if((arrString[i].match(/"/g)||[]).length % 2 === 0){ doubleString.push(arrString[i]); } else{ //"販売者 b = arrString[i] + arrString[i+1]; while((b.match(/"/g)||[]).length % 2 === 1){ b += arrString[i+1]; ++i; } doubleString.push(b); ++i; } } console.log(doubleString)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問