[[20131128131523]] 『findstrを使ってCSVの特定の列のみを検索したい』(ギャッビー) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『findstrを使ってCSVの特定の列のみを検索したい』(ギャッビー)

 コマンドプロンプトの「findstr」を使ってCSVファイルからある文字列が入ったデータを抽出しようと思ってます。

 しかし、CSVデータには、検索したい文字列が複数の列に入っている場合があります。
 仮にA列とB列とした場合、A列に該当する文字列が存在する場合のみ(行全体の)データを抽出し、B列に存在する場合は抽出しないというコマンドは可能でしょうか? 


FINDSTRコマンドは、行から文字を探すものなので、列を意識することはできない。
行頭か行末ならば指定可能。

Excel VBAで、シートに読み込んでから、列指定して検索するマクロでも作ってしまってはどうだろう?
(???) 2013/11/28(木) 13:34


こんにちは。

可能と思う。

dosにはまったく明るくないが、「findstr」を検索すると正規表現が使える
とあった。ならば「(行頭)(カンマ以外の文字が0文字以上)(目的の文字列)」
というパターンを探してはどうか。

( 佳 ) 2013/11/28(木) 13:46


あ〜できるかも。
ただ、FINDSTRの正規表現は、一般的なものと違って癖があるので注意。
例えば、カンマ6個を読み飛ばした後の列が"C"で始まる行を検索する例。

findstr /R ".*,.*,.*,.*,.*,.*,C.*" c:\test.csv

応用して、5個読み飛ばした後の列が空欄で、次の列は"C"で始まる場合。

findstr /R ".*,.*,.*,.*,.*,,.*" c:\test.csv | findstr /R ".*,.*,.*,.*,.*,.*,C.*"
(???) 2013/11/28(木) 14:18


と思ったが、空欄判定がうまくいっていない模様。
2列どちらかに指定文字、ならできるが、一方にあり他方に無し、というのがどうするのか…。
これならどうだろう?

findstr /R ".*,.*,.*,.*,.*,,C.*" c:\test.csv

(???) 2013/11/28(木) 14:27


 >???さん
 ありがとうございます。
 仮に、4列目のみ"Japan"という文字列を抽出するならばどういうコマンドになりますでしょうか?
(ギャツビー) 2013/11/28(木) 15:16

findstr /r ".*,.*,.*,japan,.*" c:\test.csv

普通の正規表現ならば「*」が不特定多数のワイルドカードになるが、
FINDSTRでは「*」は繰り返しの意味になる。更に、不特定1文字は「.」で
表されるので、「.*」が不特定多数という表現になる。正規表現もどき?

ちなみに、TAB区切りCSVだった場合にどう記述するのか不明。一般的には
「\t」なのだが…。カンマ区切り限定で使うべし。
(???) 2013/11/28(木) 16:08


 一般に正規表現では * は0回以上の繰り返しの意味なので、おかしくないと思います。
 (コマンドのワイルドカードと正規表現は別なので)

 ですから正規表現で下記は
 > 4列目のみ"Japan"という文字列
 findstr /R "^[^,]*,[^,]*,[^,]*,[^,]*Japan"
 といった感じでは無いでしょうか。

 Japan を含むではなく、Japan そのものだけを引き出したければ
 findstr /R "^[^,]*,[^,]*,[^,]*,Japan"

(Mook) 2013/11/28(木) 16:36


 なんてえらそうに書いたら、佳さんがすでに書いていましたね。

 FindStr の正規表現が簡易なのは通常の正規表現に比べて使える表現が少ないだけであって、
 使えるものは一般的なものだと思います。
http://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE
(Mook) 2013/11/28(木) 16:44

 >???さん、Mookさん

 コメントありがとうございました。
 でも残念ながらうまく行きませんでした。(=抽出結果0)
 念のため対象CSVファイルの形を言いますね。

 ある経済データで、全10列あり、4列目と5列目が国名になっています。
 このうち4列目に"Japan"が含まれているデータを抽出したいという事です。
 5列目は対象にしません。(ちなみに4列目と5列目に同じ国名が入るデータ行は存在しません)
 度々お手数かけますがよろしくお願い致します。

(ギャツビー) 2013/11/28(木) 17:38


私のサンプルでは全て小文字になっていたので、先頭大文字ではどうですか?
全角半角も完全一致していること。前空白とか後ろ空白も無いことを確認。
(???) 2013/11/28(木) 17:43

こんにちは。

◇一方にあり他方に無し、というのがどうするのか

ああ、見落としていました。
これは正規表現では難しいかも。正規表現はパターンに合う文字列にマッチする
のであって、パターンに合わない文字列にマッチするのではないから。

findstr自体に、一致しない行を返す機能がないと厳しいかも。

( 佳 ) 2013/11/28(木) 18:38


 >ちなみに4列目と5列目に同じ国名が入るデータ行は存在しません
 であれば、これは結局余計な条件で4列目にさえあればいいということではないですか?

 上の例で出ないのはなぜかわかりませんが、/I(大文字小文字を無視する)を付けても
 変わらないでしょうか。

 いろいろ悩むより、EXCEL で開いてフィルタした方が早そうですが・・・。

(Mook) 2013/11/28(木) 22:53


 >???さん、先頭大文字でもダメでした^^;

 >佳さん、厳しいですか・・

 >Mookさん
 /Iを付けても変わりませんね・・
 たしかに、4列目にさえあればいいということですね 
 (ちなみに findstr /R "Japan" にすると、5列目にJapanが存在するデータも拾ってしまいます)

(ギャツビー) 2013/11/29(金) 10:25


こんにちは。

◇たしかに、4列目にさえあればいいということですね
ということなら私の2つ目のコメントは読み流していただいて
構いません。

具体的にうまくいかないデータとコードを提示されてはいかがでしょう。
回答者がそのままコピペして確認できるレベルのものが好ましいですね、

( 佳 ) 2013/11/29(金) 10:42


 それと実際に4行目にJapan とあって抽出されないデータを丸ごと1行提示できませんか。
 どうもデータ起因である気がします。例えばデータ中に「,」や改行があるとか。

 文字列として処理する場合はデータ構造まで解析できませんから、どうしてもテキスト
 ベースで処理したいのあればlogParser などのデータ構造を扱えるツールを探してはと思います。
(Mook) 2013/11/29(金) 11:17

 >了解しました。ではデータ(をテキストエディタで開いたものを)載せますね。

 Year	Flow	Code	Reporter	Partner	Value	Netweight	Unit	Quantity2
 2011	Export	871639	Albania	Serbia	20296	10100	N	2
 2011	Export	871639	Algeria	World	20296	10100	N	2
 2011	Export	1	Brazil	Italy	997424	2869	NO	8
 2011	Export	271600	Canada	World	66117464	44555	E	1225026
 2011	Export	271600	Canada	Austria	867071	6444454	E	14360
 2011	Export	271600	Japan	Bulgaria	325736	1736181	E	5040
 2011	Export	271600	Japan	Czech Rep.	8383508	0	E	142707
 2011	Export	271600	Korea	Greece	718484	0	E	8499
 2011	Export	271600	USA	Serbia	16700681	65555	E	300458

(ギャツビー) 2013/11/29(金) 11:45


 なにも置き換え(カンマをタブに)を行っていないとして。

 データがタブで区切られているファイルはCSV(カンマ区切りデータ)とは呼ばないが。
(ねむねむ) 2013/11/29(金) 12:08

 追記で。

 現在付いている回答はデータの各項目が「,」で区切られている場合のもの。
 (最初の説明が「CSV」だったため)
  FindStr の正規表現について調べて、回答のカンマ部分をタブに置き換えてはどうか?
(ねむねむ) 2013/11/29(金) 13:08

 失礼しました。
 以下再度掲載します。

 Year,Flow,Code,Reporter,Partner,Value,Netweight,Unit,Quantity2
 2011,Export,871639,Albania,Serbia,20296,10100,N,2
 2011,Export,871639,Algeria,World,20296,10100,N,2
 2011,Export,1,Brazil,Italy,997424,2869,NO,8
 2011,Export,271600,Canada,World,66117464,44555,E,1225026
 2011,Export,271600,Canada,Austria,867071,6444454,E,14360
 2011,Export,271600,Japan,Bulgaria,325736,1736181,E,5040
 2011,Export,271600,Japan,Czech Rep.,8383508,0,E,142707
 2011,Export,271600,Korea,Greece,718484,0,E,8499
 2011,Export,271600,USA,Serbia,16700681,65555,E,300458
 2011,Export,271600,U King,Slovenia,1153444,63464,E,18450
 2011,Export,271600,Zambia,Switzerland,37968541,11546870,E,735512
 2011,Export,1,Germany,World,997424,0,P,5645
 2011,Export,28,Italy,Bulgaria,110806,0,O,44465
 2011,Export,28,Russia,World,439313,311526,PP,1125
(ギャツビー) 2013/11/30(土) 17:43

 上記を D:\data.csv として保存して、
 D:\>FindStr /R "^[^,]*,[^,]*,[^,]*,[^,]*Japan" data.csv
 とすると、下記の結果になりました。

 2011,Export,271600,Japan,Bulgaria,325736,1736181,E,5040
 2011,Export,271600,Japan,Czech Rep.,8383508,0,E,142707

 元のファイルの文字コードは S JIS でしょうか。
(Mook) 2013/11/30(土) 18:21

 >Mookさん

 上記で試したところ、ほとんどの該当データを拾ったのですが、一部拾わないデータがありました。
 そこで、"*Japan"の"*"を抜いたところ、すべてのデータを拾いました。
 ありがとうございました。助かります。

(ギャツビー) 2013/11/30(土) 19:09


 "^[^,]*,[^,]*,[^,]*,[^,]*Japan"
 よりも
 "^[^,]*,[^,]*,[^,]*,[^,]Japan"
 の方が条件がきついのですが、それは意図している動きでしょうか。
 前者より後者の方が該当するものは少ないハズなのですが・・・。

 上記で終了であれば、それでもかまいませんが、継続するようであれば
 「一部拾わないデータ」を例示いただければと思います。

 [^,] は「,」 以外の文字の 「*」 0文字以上の繰り返し、なので
 1) …,[^,]*Japan は第4項目にどこかしら Japan が含まれているという意味で、
 2) …,[^,]Japan  は第4項目の2文字目から Japan がある、という意味になります。
 3) …,Japan は第4項目が1文字目からJapan がある、という意味になります。

 A,B,C,Japan...,	1),3) にマッチ
 A,B,C,XJapan...,	1),2) にマッチ
 A,B,C,何かJapan...,	1) にマッチ

 という違いがあるはずです。
 コマンドが何を意味するかは理解したうえで、利用された方が良いかと思います。

(Mook) 2013/11/30(土) 20:11


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.