여러 sed 명령이 있습니다. 관련 정보 추출
내 파일 Sample.log(ncsa.log 형식)는 다음과 같습니다.
2012_04_01_filename.log:29874:192.168.1.12 - - [16/Aug/2012:12:54:21 +0000] "GET /cxf/myservice01/v1/abc?anyparam=anything&anotherone=another HTTP/1.1" 200 3224 "-" "client name"
2012_04_01_filename.log:29874:192.168.1.12 - - [16/Aug/2012:12:54:25 +0000] "GET /cxf/myservice02/v1/XYZ?anyparam=anything&anotherone=another HTTP/1.1" 200 3224 "-" "client name"
2012_04_01_filename.log:29874:192.168.1.12 - - [16/Aug/2012:12:56:52 +0000] "GET /cxf/myservice01/v1/rsv/USER02?anyparam=anything&anotherone=another HTTP/1.1" 200 6456 "-" "client name"
2012_04_01_filename.log:29874:192.168.1.12 - - [16/Aug/2012:12:58:52 +0000] "GET /cxf/myservice01/v2/upr/USER01?anyparam=anything&anotherone=another HTTP/1.1" 200 2424 "-" "client name"
2012_04_01_filename.log:29874:192.168.1.12 - - [16/Aug/2012:12:59:11 +0000] "GET /cxf/myservice02/v1/xyz?anyparam=anything&anotherone=another HTTP/1.1" 200 233 "-" "client name"
이 파이프로 연결된 sed 세트는 필요한 URL 세부 정보를 추출합니다(첫 번째 sed: \1 = YYYY-MM-DD 날짜, \2 = service0x, \3 = 트라이그램, \4 = 선택적 엔터티 ID, \5 = HTTP 응답 코드 , \6 = http 응답 크기)
more sample.log | sed -r 's#^(...._.._..)_.*/cxf/(myservice.*)/v./(.{3})[/]*([a-Z0-9]*)?.*\sHTTP/1.1.\s(.{3})\s([0-9]*)\s.*#\1;\2;\L\3;\E\4;\5;\6#g' | sed -r 's!(.*;.*;.{3};)[a-Z0-9]+(;.*;.*)!\1retrieve\2!g' | sed -r 's!(.*);;(.*)!\1;list;\2!g' > request-by-operation.txt
원하는 결과는 다음과 같습니다.
2012_04_01;myservice01;abc;list;200;3224
2012_04_01;myservice02;xyz;list;200;3224
2012_04_01;myservice01;rsv;retrieve;200;6456
2012_04_01;myservice01;upr;retrieve;200;2424
2012_04_01;myservice02;xyz;list;200;233
list
두 개의 다른 sed 파이프(작업을 수행함)를 사용하는 것 외에 and 작업을 변환하는 다른 방법을 찾지 못했습니다 .retrieve
sed가 섹션(특정 그룹의 경우)에서 명령 교체를 지원하지 않는다고 들었지만 #\1;\2;\L\3;\Eifnull(\4, "list", "retrieve");\5;\6#
단 하나의 sed 명령을 사용하여 다른 방법으로 수행할 수 있는지 궁금합니다.
답변1
sed
교체 섹션의 명령은 호출할 수 없지만 여러 교체를 실행할 수 있습니다. 이 경우 모든 대체 항목을 하나로 묶는 것이 sed
작동하는 것 같습니다.
sed -r 's#^(...._.._..)_.*/cxf/(myservice.*)/v./(.{3})[/]*([a-Z0-9]*)?.*\sHTTP/1.1.\s(.{3})\s([0-9]*)\s.*#\1;\2;\L\3;\E\4;\5;\6#g;
s!(.*;.*;.{3};)[a-Z0-9]+(;.*;.*)!\1retrieve\2!g;
s!(.*);;(.*)!\1;list;\2!g'
답변2
원하는 부분을 선택할 수 있지만 원하지 않는 부분을 삭제할 수도 있습니다.
sed '
s|_[^_]* /[^/]*/|;|
s|/[^/]*/\(...\)|;\L\1|
s|?[^"]*" |;list;|
s|/.*;|;retrieve;|
s/ /;/
s/ .*$//'
답변3
GNU sed에는 명령이 있지만 s///e
다음을 보냅니다.모두평가를 위해 쉘에 대한 패턴 공간:
$ echo "echo hello world" | sed 's/world/foo bar | rev/e'
rab oof olleh
따라서 "world"는 "foo bar | rev"로 대체됩니다. 패턴 공간은 이제 "echo hello foo bar | rev"입니다. 이는 쉘로 전송되고 출력은 패턴 공간에 배치된 다음 암시적으로 인쇄됩니다.
Perl의 e
플래그를 사용하면 문자열에서 일치하는 부분에만 집중할 수 있습니다.
바라보다https://www.gnu.org/software/sed/manual/sed.html#The-_0022s_0022-command
이자형
이 명령을 사용하면 쉘 명령의 입력을 패턴 공간으로 파이프할 수 있습니다. 대체가 이루어지면 패턴 공간에 있는 명령이 실행되고 해당 출력이 패턴 공간을 대체합니다. 후행 줄 바꿈은 억제됩니다. 실행할 명령에 null 문자가 포함되어 있으면 결과가 정의되지 않습니다. 이것은 GNU sed 확장입니다.