オプションのグループは一致しません。

オプションのグループは一致しません。

以下は、私が解決したい問題の単純化されたバージョンです。私はこのファイルを持っています:

1 H 200 OK.Content-Length: 2422 x
2 H 403 Forbidden.z

私はHTTPステータスと-存在する場合-コンテンツの長さと一致するようにsedを取得しようとしました。

> sed -nEe 's,^.*H ([ 0-9a-zA-Z]+).*(Content-Length: ([0-9]+))?.*$,\1 \3,p' x
200 OK 
403 Forbidden 

したがって、オプションのグループは絶対に一致しません。疑問符を削除してオプションでないものにすると、コンテンツの長さと一致しますが、疑問符のない行は一致しません。

> sed -nEe 's,^.*H ([ 0-9a-zA-Z]+).*(Content-Length: ([0-9]+)).*$,\1 \3,p' x
200 OK 2422

次の出力を提供するようにsedを取得するにはどうすればよいですか?

200 OK 2422 
403 Forbidden 

注意:遅延マッチング()をサポートするPerlも試しましたが、.*?成功しませんでした。

> perl -pe 's,^.*H ([ 0-9a-zA-Z]+).*?(Content-Length: ([0-9]+))?.*?$,\1 \3,' x
200 OK 
403 Forbidden 

ベストアンサー1

グループはオプションなので、(Content....)貪欲なバージョンでは次のことを行います。

1 H 200 OK.Content-Length: 2422 x

^.*H ([ 0-9a-zA-Z]+)match 1 H (200 OK)、それから.*最後まで一致し、(Content-Length: ([0-9]+))?次の.*両方が行末の空の文字列と一致します。

non-greedyバージョンでは、最初のものは.*?できるだけ少なく一致しようとしますが、残りの行(.Content-Length: 2422 x)は一致し、(Content-Length: ([0-9]+))?それ以降の.*?$行の終わりまではすべて一致しないので大丈夫です。

.*最初のキャプチャ後、最初のエントリがaをスクロールしないことを確認する必要があります Content-Length: \d+。たとえば、各段階で否定的な予測を使用します。

perl -lne 'print if
 s/^.*?H ([\s\w]+)(?:(?!Content-Length: \d+).)*(?:Content-Length: (\d+))?.*$/\1\2/'

単にこれを行うこともできますが:

perl -lne '
  if (/H\s+([\s\w]+)(.*)/) {
    my $status = $1;
    print "$status" . ($2 =~ /Content-Length: (\d+)/ && " $1");
  }'

または:

sed -nE 's/^.*H[[:space:]]+([[:space:][:alnum:]]+).*Content-Length: ([[:digit:]]+).*$/\1 \2/p;t
         s/^.*H[[:space:]]+([[:space:][:alnum:]]+).*$/\1/p'

つまり、一度に置き換えようとしないでください。

おすすめ記事