Aかつ(Bの否定)No.09543
Alter Ego さん 17/09/08 09:28
 
grep検索で質問なのですが、A and not B のような検索はどう入力すればいいのでし
ょうか?検索するとユニックスやリナックスでは A | -v B のように書くみたいで
すが、秀丸のgrepではうまくいきません。

[ ]
RE:09543 Aかつ(Bの否定)No.09544
でるもんたいいじま さん 17/09/08 09:45
 
こんにちは。秀丸愛用者の「でるもんた・いいじま」と申します。

> grep検索で質問なのですが、A and not B のような検索はどう
> 入力すればいいのでしょうか?

たぶん、「単一の正規表現でそれを表現する一般的な方法は存在しない」
というのが答になると思います。AとBに共通部分がいくらかでもあれば、
(?...) を使ってうまく書けるかもしれません。

> 検索するとユニックスやリナックスでは A | -v B のように書く
> みたいですが、秀丸のgrepではうまくいきません。

この文脈からすると、コマンドラインからの操作でしょうか?
コマンドラインの場合、
$ grep 'A | -v B' *.txt
ではダメなはずです。最低でも、
$ grep 'A' *.txt | grep -v 'B'
としなければいけません。

しかも、この検出は行単位ですので、「Aに該当して、Bに該当しない行」が
すべてヒットします。つまり、「ファイルのどこか一部分がAにヒットして、
「そのファイルのどこも」Bにヒットしない、そういうものだけをリスト
アップしたい、という要望は上記のコマンドではできません。

もしそういうことであれば、ちょっと手の込んだスクリプトを書くことに
なります。(あー、でもxargsを使えば簡単に書けそうな気もするな…(笑))

もし秀丸でそういう仕様をご希望であれば、これは間違いなくマクロでの
作業になると思いますし、もし文字コードの問題がなければ、grep.exeと
xargs.exeをmsysあたりから引っ張ってきて呼び出すのが楽だと思います。

[ ]
RE:09544 Aかつ(Bの否定)No.09547
秀丸担当 さん 17/09/08 11:42
 

もし行単位ということでしたら正規表現で以下のような書き方ができるようです。
^(?!.*B).*(?=A).*$

ファイル単位ということでしたら正規表現で書く方法は無いです。
それなりの凝ったマクロを作る必要が出てくると思います。

または、ファイル単位で手動だけでやる場合、grepダイアログで「ファイル名一
覧だけ作成」をONにして、Aのgrep結果とBのgrep結果を2つの秀丸エディタに出
し、その内容を比較すると近い感じにできると思います。
[ウィンドウ]→[他の秀丸エディタと内容比較...]で「カラーマーカーで色付
け」をONにして、さらに「...」の中の「常に行単位」をONにすると視覚的にわ
かりやすいくなると思います。

[ ]
RE:09547 Aかつ(Bの否定)No.09548
秀丸担当 さん 17/09/08 12:03
 

ファイル単位で手動だけでやる場合の比較ですが、比較するにはもうひと手間、
行番号部分を消す作業が必要でした。
例えば「\(\d+\)$」を空の文字列に置換して削除ができると思いますが、手動で
やるには手間が多いかもしれません。

[ ]
RE:09544 Aかつ(Bの否定)No.09549
Iranoan さん 17/09/08 12:23
 
Alter Ego さん、でるもんたいいじまさん今日は、Iranoan です
> しかも、この検出は行単位ですので、「Aに該当して、Bに該当しない行」が
> すべてヒットします。つまり、「ファイルのどこか一部分がAにヒットして、
> 「そのファイルのどこも」Bにヒットしない、そういうものだけをリスト
> アップしたい、という要望は上記のコマンドではできません。
>
> もしそういうことであれば、ちょっと手の込んだスクリプトを書くことに
> なります。(あー、でもxargsを使えば簡単に書けそうな気もするな…(笑))
Alter Ego さんがどちらを希望か解りませんが、ファイル単位だと UNIX 系の grep
コマンドだと、
$ grep -l "A" *.txt | xargs grep -L "B"
で出来ますね

どちらにしても一回の grep コマンドでは出来ませんね

[ ]
RE:09549 Aかつ(Bの否定)No.09550
でるもんたいいじま さん 17/09/08 17:15
 
でるもんた・いいじまです。

いいじま:
> あー、でもxargsを使えば簡単に書けそうな気もするな…(笑)

Iranoanさん:
> ファイル単位だと UNIX 系の grep コマンドだと、
> $ grep -l "A" *.txt | xargs grep -L "B"
> で出来ますね

おお、一発ですね。実は私、UNIX系OSを丸々20年触っていながら一度も
xargs を自力で使ったことがないフヌケなので、ここまで綺麗に書ける
というのは感動です。

#よほどヒット数が多くなければ cmd1 > /tmp/lst && cmd2 `cat /tmp/lst`
#とか、あるいは cmd1 の実行結果をコンソールエミュレータからマウスで
#コピペして cmd2 `cat` したりとかで間に合っちゃうもので…(汗)

grepコマンドの唯一の難点は、文字コードが複数混在している場合には
どうしようもない、というところですかね。文字コード自動判別つきの
grepクローンがあればいいんですけど、それをUNIXベースのシステムで
実装しようとすると、Unicodeと各言語の文字コードとのマッピング
テーブルをどうするか、という罠にはまりそう…。

[ ]
RE:09550 Aかつ(Bの否定)No.09551
Iranoan さん 17/09/08 21:46
 
でるもんたいいじまさん今日は、Iranoan です
> grepコマンドの唯一の難点は、文字コードが複数混在している場合には
> どうしようもない、というところですかね。文字コード自動判別つきの
> grepクローンがあればいいんですけど、それをUNIXベースのシステムで
> 実装しようとすると、Unicodeと各言語の文字コードとのマッピング
> テーブルをどうするか、という罠にはまりそう…。
nkf や iconv を噛まして、シェルスクリプトにすれば、出来ますね
for f in *.txt
do
 nkf "$f" | grep -ql "A"
 if [ $? -eq 0 ]; then
  nkf "$f" | grep -ql "B"
  if [ $? -eq 1 ]; then
   echo "$f"
  fi
 fi
done
一行で書けば、(などで次の 2 行は実際には 1 行)
for f in *.txt; do nkf "$f" | grep -ql "A"; if [ $? -eq 0 ]; then
nkf "$f" | grep -ql "B" if [ $? -eq 1 ]; then echo "$f"; fi; fi; done

もっとスマートな方法が有ると思いますが、
・思いつかない
・Alter Ego さんの本意が解らない
・秀丸エディタの話題から外れる
ので、ここまでですね

[ ]