CSV 파일에 테스트 결과가 있습니다. 첫 번째 필드에는 밀리초 단위의 타임스탬프가 있습니다.
다음은 CSV 파일의 샘플 레코드입니다.
1628689875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
램프 업(시작 시간으로부터 5분) 및 램프 다운 기간(지난 5분) 동안의 테스트 결과를 삭제하고 필터링된 테스트 결과를 CSV 파일에 쓰고 싶습니다.
하드코딩된 값을 사용해 보았습니다.
#!/usr/bin/awk -f
BEGIN {
endTime=1628689875326
startTime=1628689875326-300*1000
offset=1628689875326-3900*1000
FS=","
rowCount=0
}
{
if ($1> startTime && $1<offset){
rowCount++
print $0
}
}
답변1
awk를 호출하기 위해 shebang을 사용하는 대신 shebang을 사용하여 쉘을 호출한 다음 awk를 호출하십시오. 바라보다https://stackoverflow.com/a/61002754/1745001왜.
나는 당신이 원하는 것을 할 것입니다:
#!/usr/bin/env bash
awk -F',' '
NR==FNR {
if (NR==2) {
fiveMins = 5*60*1000*1000
begTime = $1 + fiveMins
}
endTime = $1 - fiveMins
next
}
(FNR==1) || ( (begTime <= $1) && ($1 <= endTime) ) {
print
rowCount++
}
END {
print rowCount+0 | "cat>&2"
}
' "$1" "$1"
tail
또는 다음을 사용하여 마지막 행의 타임스탬프를 얻을 수 있습니다.@GreenOnline의 답변) awk에서 파일을 두 번 읽는 대신:
#!/usr/bin/env bash
awk -v lastTime="$(tail -n 1 "$1" | cut -d',' -f1)" -F',' '
NR==2 {
fiveMins = 5*60*1000*1000
begTime = $1 + fiveMins
endTime = lastTime - fiveMins
}
(NR==1) || ( (begTime <= $1) && ($1 <= endTime) ) {
print
rowCount++
}
END {
print rowCount+0 | "cat>&2"
}
' "$1"
어느 쪽이든 다음과 같이 호출할 수 있습니다.
scriptname input.csv > output.csv
> output.csv
또는 출력 파일 이름을 하드코딩해도 괜찮다면 쉘 스크립트에서 awk 스크립트 뒤에 추가하십시오.
위의 내용은 CSV에 출력에 인쇄하려는 헤더 행이 있다고 가정합니다.
Shebang을 사용하지 않고 awk를 호출하면 쉘을 사용하여 가장 잘하는 작업, 즉 다른 명령을 호출하고 스크립트 인수를 여러 번 사용한 다음 awk를 호출하여 가장 잘하는 작업, 즉 텍스트를 처리할 수 있습니다. 부팅 비율 다른 방법은 더 깨끗하고 강력하며 효율적인 스크립트입니다.
답변2
하드 코딩된 솔루션
하드코딩된 시간 스크립트에서 문제는 다음과 같습니다.
offset
보다 작startTime
으므로if
조건은$1> startTime && $1<offset
할 수 있는안 돼요그건 진실이야.
그 이유는 아직 5분( =300초) startTime
이 남았는데 , 아직 65분( =3900초) 이 남아 있기 때문입니다.5*60
offset
65*60
해결책은 초기화 프로그램을 다음으로 변경하는 것입니다.
startTime=1628689875326-3900*1000*1000
offset=1628689875326-300*1000*1000
그러면 관련 시간이 다음으로 설정됩니다.
endTime = 1628689875326
startTime = endTime - (3900*1000*1000) = 1624789875326
5 minutes before end = endTime - (300*1000*1000) = 1628389875326
이제 다음과 같은 로그 파일이 제공됩니다.
1624789875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628689875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
달리기
more test.log | ./filter.awk
원하는 결과를 제공합니다
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
더 나은 솔루션 - 시작 시간 확인
그러나 귀하의 질문을 자세히 조사해 보면 몇 가지 사항이 잘 정의되어 있지 않은 것으로 나타났습니다.
스크립트에서는
startTime
실제 로그의 시작이 아니라 필터의 시작일 수 있습니다. 로그의 시작 시간은 5분 전입니다.1624789875326 - 300*1000*1000 = 1624489875326
당신은 시간이 밀리초 단위라고 말
*1000*1000
했지만마이크로초.
그럼에도 불구하고, 시작 시간(로그 파일의 첫 번째 줄부터 시작)을 자동으로 찾고 램프 시간을 계산하여 필터의 시작 시간을 계산하는 솔루션이 있습니다.
또한 필터 시간의 끝도 계산합니다(하드코딩된 스크립트와 동일한 방식).종료 시간을 입력해야 하지만, 이는 로그의 마지막 타임스탬프입니다.
#!/usr/bin/awk -f
BEGIN {
rampTimeMins=5
rampTimeMillis=rampTimeMins*60*1000
rampTimeMicros=rampTimeMins*60*1000*1000
# Enter the start time
# (not required, if NR conditional is used)
startTime=0
# Calculate Start filter time in microseconds
# (not required, if NR conditional is used)
filterStartTime=startTime+rampTimeMicros
# Enter the end time (required)
endTime=1628689875326
# Calculate End filter time in microseconds
filterEndTime=endTime-rampTimeMicros
FS=","
rowCount=0
}
{
if (NR==1){
startTime=$1
filterStartTime=startTime+rampTimeMicros
}
if ($1> filterStartTime && $1<filterEndTime){
rowCount++
print $0
}
}
END {
print rowCount
}
참고 1: CSV의 첫 번째 행이 헤더인 경우 NR==1
다음으로 변경하세요.NR==2
노트 2: 마이크로초 대신 밀리초를 사용하려면 rampTimeMicros
로 변경하면 됩니다 rampTimeMillis
.
다음은 다음을 포함하는 샘플 로그 파일입니다.추가의로그의 실제 시작 시간인 초기 시간(필터의 시작 시간이 아님)
1624489875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624489875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624789875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628689875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
어느 것으로 실행할 것인가
more test.log | ./filter.awk
이전과 동일한 결과를 제공합니다
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
2
하지만 추가 줄이 있습니다.
최종 솔루션 - 종료 시간 얻기
줄을 바꾸면
endTime=1628689875326
도착하다
"tail -1 test.log | cut -d, -f1" | getline endTime
그러면 마지막 타임스탬프를 얻었으므로 스크립트를 더 이상 편집할 필요가 없습니다.앞으로스크립트가 실행됩니다. 일반 용도로 제작됨
"tail -1 "ARGV[1]" | cut -d, -f1" | getline endTime
또는 더 나은 방법은 (안전한 측면을 유지하기 위해) 다음과 같이 생성된 하위 쉘에 인용된 파일 이름을 전달하는 것입니다.에드의 코멘트:
생성된 하위 쉘에 따옴표 없이 파일 이름을 전달하지 않도록 으로 변경합니다(이 모든 것은 글로빙, 토큰화, 보안 등을 의미함
"tail -1 "ARGV[1]"
) ."tail -1 \047"ARGV[1]"\047
\047
작은따옴표(FWIW: \042
큰따옴표)는 어디에 있습니까?
"tail -1 \047"ARGV[1]"\047 | cut -d, -f1" | getline endTime
따라서 최종 스크립트는 다음과 같습니다.
#!/usr/bin/awk -f
BEGIN {
rampTimeMins=5
rampTimeMillis=rampTimeMins*60*1000
rampTimeMicros=rampTimeMins*60*1000*1000
# Enter the start time
# (not required, if NR conditional is used)
startTime=0
# Calculate Start filter time in microseconds
# (not required, if NR conditional is used)
filterStartTime=startTime+rampTimeMicros
# Derive the end time
"tail -1 \047"ARGV[1]"\047 | cut -d, -f1" | getline endTime
# Calculate End filter time in microseconds
filterEndTime=endTime-rampTimeMicros
FS=","
rowCount=0
}
{
if (NR==1){
startTime=$1
filterStartTime=startTime+rampTimeMicros
}
if ($1> filterStartTime && $1<filterEndTime){
rowCount++
print $0
}
}
END {
print rowCount
}
참고 1: CSV의 첫 번째 행이 헤더인 경우 NR==1
다음으로 변경하세요.NR==2
다음 명령( filter.awk
) 을 사용하여 스크립트를 실행합니다.
./filter.awk test.log
아니요
more test.log | ./filter.awk
인용하다:
답변3
주어진 예제 스크립트는 다음 수정 사항으로 업데이트되었습니다.
- 입력 파일의 두 번째 줄의 시작 시간을 기준으로
filterStartTime
합계를 계산합니다.filterEndTime
- 추가 분석을 위해 파일에 출력 쓰기
#!/usr/bin/awk -f
BEGIN {
testDurationMins=60
rampTimeMins=5
outputFileName="test-result-filtered-without-rampup.jtl"
rampTimeMillis=rampTimeMins*60*1000
# Enter the start time
# (not required, if NR conditional is used)
startTime=0
# Calculate Start filter time in milliseconds
# (not required, if NR conditional is used)
filterStartTime=startTime+rampTimeMillis
# Filter end time
filterEndTime=0
# Calculate the test duration in milliseconds
testDurationMillis=testDurationMins*60*1000
FS=","
rowCount=0
}
{
if (NR==1){
#Write header to the output file
print > outputFileName
}
if (NR==2){
#Set the filter start and end times
startTime=$1
filterStartTime=startTime+rampTimeMillis
filterEndTime=filterStartTime+testDurationMillis
}
if (NR>2 && $1> filterStartTime && $1<filterEndTime){
rowCount++
print >> outputFileName
}
}
END {
print "" rowCount
}