9

次の形式でHive QLの「外部テーブルの作成」ステートメントにフィードできる正規表現を探しています

"input.regex"="the regex goes here"

条件は、RegexSerDe が読み取る必要があるファイル内のログが次の形式であることです。

2013-02-12 12:03:22,323 [DEBUG] 2636hd3e-432g-dfg3-dwq3-y4dsfq3ew91b Some message that can contain any special character, including linebreaks. This one does not have a linebreak. It just has spaces on the same line.
2013-02-12 12:03:24,527 [DEBUG] 265y7d3e-432g-dfg3-dwq3-y4dsfq3ew91b Some other message that can contain any special character, including linebreaks. This one does not have one either. It just has spaces on the same line.
2013-02-12 12:03:24,946 [ERROR] 261rtd3e-432g-dfg3-dwq3-y4dsfq3ew91b Some message that can contain any special character, including linebreaks.
 This is a special one.
 This has a message that is multi-lined.
 This is line number 4 of the same log.
 Line 5.
2013-02-12 12:03:24,988 [INFO] 2632323e-432g-dfg3-dwq3-y4dsfq3ew91b Another 1-line log
2013-02-12 12:03:25,121 [DEBUG] 263tgd3e-432g-dfg3-dwq3-y4dsfq3ew91b Yet another one line log.

次の外部テーブル作成コードを使用しています。

CREATE EXTERNAL TABLE applogs (logdatetime STRING, logtype STRING, requestid STRING, verbosedata STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES
(
"input.regex" = "(\\A[[0-9:-] ]{19},[0-9]{3}) (\\[[A-Z]*\\]) ([0-9a-z-]*) (.*)?(?=(?:\\A[[0-9:-] ]{19},[0-9]|\\z))",
"output.format.string" = "%1$s \\[%2$s\\] %3$s %4$s"
)
STORED AS TEXTFILE
LOCATION 'hdfs:///logs-application';

つまりね:

各ログのすべての最初の行を取得できます。ただし、複数の行があるログの他の行は対象外です。すべてのリンクを試し、最後に に置き換え\z、andまたはに置き換えましたが、何も機能しませんでした。output.format.string に何か不足していますか? または、正規表現を適切に使用していませんか?\Z\A^\Z\z$%4$s

正規表現の機能:

最初にタイムスタンプに一致し、次にログタイプ (DEBUGまたはINFOその他)、次にID(小文字のアルファベット、数字、およびハイフンの組み合わせ) に続いて、次のタイムスタンプが見つかるまで、または入力の最後が見つかるまで、すべてが続きます。最後のログ エントリと一致します。また、最後に を追加しようとし/mましたが、その場合、生成されたテーブルにはすべて NULL 値が含まれます。

4

3 に答える 3

1

正規表現には多くの問題があるようです。

まず、二重角かっこを削除します。

次に、\Aおよび\Z/は、行だけでなく、入力\zの最初と最後に一致するようにします。に変更して行頭に一致させますが、この場合、実際には入力の終わりに一致させたいので、 に変更しないでください。\A^\z$

(.*?)第三に、ではなくに一致させたい(.*)?。最初のパターンは貪欲ではありませんが、2 番目のパターンは貪欲ですがオプションです。入力の終わりが続くことを許可したので、入力全体を最後まで一致させる必要があります。

第 4 に、.改行に一致しません。(\s|\S)代わりに、または([x]|[^x])など、無料のマッチの任意のペアを使用できます。

\A第 5 に、 and \Z/との単一行の一致が得られた\z場合、文字列全体を固定していたため、入力も単一行でした。

一致\nするものがない場合、改行は含まれません。

/m正規表現には区切り文字が含まれていないため、最後に追加することはできません。代わりにリテラル文字との一致を試みるため、一致/mが得られません。

それが機能する場合、必要な正規表現は次のようになります。

"^([0-9:- ]{19},[0-9]{3}) (\\[[A-Z]*\\]) ([0-9a-z-]*) ([\\s\\S]*?)(?=\\r?\\n([0-9:-] ){19},[0-9]|\\r?\\z)"

壊す:

^([0-9:- ]{19},[0-9]{3}) 

:改行の開始と、数字、 、-またはコンマ、3 桁の数字、およびスペースの19 文字に一致します。最後のスペース (タイムスタンプ) を除くすべてをキャプチャします。

(\\[[A-Z]*\\]) 

リテラル[、任意の数の大文字に一致します。大文字がない場合でも、リテラル]とスペースに一致します。最後のスペース (エラー レベル) を除くすべてをキャプチャします。

([0-9a-z-]*) 

任意の数の数字、小文字、または-スペースに一致します。最後のスペース (メッセージ ID) を除くすべてをキャプチャします。

([\\s\\S]*?)(?=\\r?\\n([0-9:-] ){19},[0-9]|\\r?\\Z)

任意の空白文字または非空白文字 (任意の文字) に一致しますが、 ungreedy には一致します*?。新しいレコードまたは入力の終わり( \Z) がすぐ前にある場合、一致を停止します。この場合、出力に 1 行しか表示されないため、行末に一致させたくありません。最終 (メッセージ テキスト) 以外のすべてをキャプチャします。は\r?\n、メッセージの最後にある最後の改行をスキップします\r?\Z。また、次のように書くこともできます\r?\n\z。注: 大文字\Zには、入力の最後に最後の改行がある場合、それが含まれます。小文字\zは入力の末尾のみで一致し、入力の末尾の前の改行は一致しません。\z?Windows の行末を処理する必要がある場合に備えて追加しましたが、これは必要ではないと思います。

ただし、ファイル全体を行ごとではなく一度にフィードできない限り、これも機能しないと思われます。

試すことができる別の簡単なテストは次のとおりです。

"^([\\s\\S]+)^\\d"

それが機能する場合、次の行の行番号 (タイムスタンプの最初の桁) が続く行全体に一致します。

于 2014-09-27T11:50:56.467 に答える
1

次の Java 正規表現が役立つ場合があります。

(\d{4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},\d{1,3})\s+(\[.+?\])\s+(.+?)\s+([\s\S\s]+?)(?=\d{4}-\d{1,2}-\d{1,2}|\Z)

壊す:

  • 第1捕獲グループ(\d{4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},\d{1,3})
  • 第二捕獲グループ(\[.+?\])
  • 3番目の捕獲グループ(.+?)
  • 4番目の捕獲グループ([\s\S]+?)

(?=\d{4}-\d{1,2}-\d{1,2}|\Z)正の先読み - 以下の正規表現が一致することをアサートします。第 1 の代替: .第 2 の\d{4}-\d{1,2}-\d{1,2}代替:\Z文字列の末尾の位置をアサートします。

参照http://regex101.com/

于 2014-10-25T09:39:08.550 に答える
0

Hive についてはよくわかりませんが、次の正規表現、または Java 文字列用にフォーマットされたバリエーションが機能する可能性があります。

(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d,\d+) \[([a-zA-Z_-]+)\] ([\w-]+) ((?:[^\n\r]+)(?:[\n\r]{1,2}\s[^\n\r]+)*)

これは、次のサンプル データと一致することがわかります。

http://rubular.com/r/tQp9iBp4JI

内訳:

  • (\d{4}-\d\d-\d\d \d\d:\d\d:\d\d,\d+)日時(捕獲グループ1)
  • \[([a-zA-Z_-]+)\]ログ レベル (キャプチャ グループ 2)
  • ([\w-]+)リクエスト ID (キャプチャ グループ 3)
  • ((?:[^\n\r]+)(?:[\n\r]{1,2}\s[^\n\r]+)*)潜在的に複数行のメッセージ (キャプチャ グループ 4)

最初の 3 つのキャプチャ グループは非常に単純です。

最後のものは少し奇妙かもしれませんが、ルビュラーで動作しています。内訳:

(                       Capture it as one group
    (?:[^\n\r]+)        Match to the end of the line, dont capture
    (?:                 Match line by line, after the first, but dont capture
        [\n\r]{1,2}     Match the new-line
        \s              Only lines starting with a space (this prevents new log-entries from matching)
        [^\n\r]+        Match to the end of the line            
    )*                  Match zero or more of these extra lines
)

[^\n\r]の代わりに使用したのは、改行を一致させる.ように見えるためです( link):RegexSerDe.

// Excerpt from https://github.com/apache/hive/blob/trunk/contrib/src/java/org/apache/hadoop/hive/contrib/serde2/RegexSerDe.java#L101
if (inputRegex != null) {
  inputPattern = Pattern.compile(inputRegex, Pattern.DOTALL
      + (inputRegexIgnoreCase ? Pattern.CASE_INSENSITIVE : 0));
} else {
  inputPattern = null;
}

お役に立てれば。

于 2014-09-30T02:41:39.130 に答える