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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

正規表現

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

6296閲覧

C言語のregex.hライブラリを使っての正規表現がうまくいきません。

shimaokazu

総合スコア26

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

正規表現

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/01/02 12:18

ポートスキャンツールnmapコマンドの結果から正規表現で、ある行を抽出したいのですが、それがうまくいきません。
使用言語はc言語で、regex.hというc言語の正規表現ライブラリを使用しています。

例えばポートスキャンをして、以下の結果が出たとします。

Starting Nmap 6.40 ( http://nmap.org ) at 2016-01-01 12:00 JST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0000080s latency).
Not shown: 995 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http

Nmap done: 1 IP address (1 host up) scanned in 2.44 seconds

そこから[22/tcp open ssh〜80/tcp open http]という部分を抽出したいのですが、それがうまくいきません。

正規表現パターンが以下です。
(\d+)?\/(tcp|udp).+(open|closed|filtered).+

patternMatch[i].rm_soにマッチした最初の文字の位置が入るのですが、これの最初の文字の位置が[22/tcp open ssh]の[/]が最初の位置として入ってしまいます。

patternMatch[i].rm_eoに最後の文字の位置が入るのですが、これも[Nmap done: 1 IP address (1 host up) scanned in 2.44 seconds]の[seconds]の中の最後の[s]が入ってしまいます。

(ちなみにpatternMathはchar型配列の変数です)

正規表現のパターンが間違っていると思うのですが、正規表現の勉強を初めてまだ浅くかなりいろいろ試しているのですが、うまくいきません。

[22/tcp open ssh〜80/tcp open http]が抽出できる正規表現のパターンを教えて頂けないでしょうか。

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

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

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

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

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

guest

回答1

0

ベストアンサー

C言語のregex.hは正直使ったこと無いので詳しくは無いんですが。

どうやら、regex.hはPOSIX標準の正規表現ライブラリーなので、Perl拡張の正規表現の文字クラスである\d(C言語上のリテラルでは\\d)は対応していないようです。

なので、POSIX標準でも対応している[0-9]を使えば良さそうです。

参考までに、試したコードを載せておきます。

  • サンプルコード

lang

1#include <stdio.h> 2#include <regex.h> 3 4#define N 4 5 6int main() 7{ 8 regex_t reg; 9 regmatch_t match[N]; 10 int i, j, k; 11 12 const char *pattern = "([0-9]+)?\\/(tcp|udp).+(open|closed|filtered).+"; 13 char *s[] = { 14 "Starting Nmap 6.40 ( http://nmap.org ) at 2016-01-01 12:00 JST", 15 "Nmap scan report for localhost (127.0.0.1)", 16 "Host is up (0.0000080s latency).", 17 "Not shown: 995 closed ports", 18 "PORT STATE SERVICE", 19 "22/tcp open ssh", 20 "80/tcp open http", 21 "", 22 "Nmap done: 1 IP address (1 host up) scanned in 2.44 seconds", 23 }; 24 const int size = sizeof s / sizeof s[0]; 25 26 regcomp(&reg, pattern, REG_EXTENDED); 27 28 for (i = 0; i < size; i++) { 29 printf("[%s] => ", s[i]); 30 if (regexec(&reg, s[i], N, match, 0) == REG_NOMATCH) { 31 printf("not matched."); 32 } else { 33 printf("matched. ["); 34 for (j = 0; j < N; j++) { 35 for (k = match[j].rm_so; k < match[j].rm_eo; k++) { 36 putchar(s[i][k]); 37 } 38 printf(", "); 39 } 40 printf("]"); 41 } 42 printf("\n"); 43 } 44 45 regfree(&reg); 46 47 return 0; 48}
  • 実行結果
[Starting Nmap 6.40 ( http://nmap.org ) at 2016-01-01 12:00 JST] => not matched. [Nmap scan report for localhost (127.0.0.1)] => not matched. [Host is up (0.0000080s latency).] => not matched. [Not shown: 995 closed ports] => not matched. [PORT STATE SERVICE] => not matched. [22/tcp open ssh] => matched. [22/tcp open ssh, 22, tcp, open, ] [80/tcp open http] => matched. [80/tcp open http, 80, tcp, open, ] [] => not matched. [Nmap done: 1 IP address (1 host up) scanned in 2.44 seconds] => not matched.


参考リンク

正規表現メモ
http://www.kt.rim.or.jp/~kbk/regex/regex.html

正規表現 - Wikipedia
https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE

投稿2016/01/03 03:26

編集2016/01/04 11:42
argius

総合スコア9388

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

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

shimaokazu

2016/01/04 10:39

回答ありがとうございます。 正規表現パターンを試したところ、実際に抽出することに成功しました。 もうひとつ質問で申し訳ないのですが、今度は[22/tcp open ssh]でいうなら、[ssh]も取り出したいのですが、そこがうまくいきません。 [([0-9]+)?\\/(tcp|udp).+(open|closed|filtered)((\\s)+?).+]と[([0-9]+)?\\/(tcp|udp).+(open|closed|filtered)((\\s)+?)((\\l)+?)]を試しましたが、結果は変わりませんでした。 正しいパターンを教えて頂けないでしょうか。
argius

2016/01/04 13:28 編集

\sなどもPerlの拡張なので、ここでは使えません。 おまけに、[:alpha:]などの文字クラスも使えないようです。 少なくとも私の環境(GCC 4.9.3 cygwin版と、OSX Apple LLVM v6.1.0)ではダメでした。 回答欄に少し参考リンクを付けておきましたので、参考にしてみてください。 ただ、残念ながら"regex.h"のサポート範囲については、資料が見つかりませんでした。 なので、\sの代わりに、"[ \t]"にしてみましょうか。 それと行末の'$'も入れておきます。 \sの代わりにするなら、[ \t\r\n]かもしれませんが、改行が来ることは想定していないので、「半角スペースorタブ文字」としました。 "([0-9]+)?\\/(tcp|udp).+(open|closed|filtered)[ \t]+([a-z]+)$" open...の前の".+"もこれに統一したほうが分かりやすいかもですね。 それと、カッコが1つ増える場合はmatch配列のサイズを増やさないといけません。 #define N 4 を 5 に増やしてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問